下面是我的方法的代码,在该方法中,我试图让 boids 不与障碍物发生碰撞,同时尽可能少地改变它们的路径:
def avoidcircle(self, circleobstacle):
colliding = True
while(colliding == False):
newvector = [self.posvector[0] - circleobstacle.x, self.posvector[1] - circleobstacle.y]
multiplythem = newvector.normalize().dot(self.velocity.normalize())
a_angleinradian = math.acos(multiplythem)
(Px, Py) = (self.posvector[0], self.posvector[1])
(Cx, Cy) = (circleobstacle.x, circleobstacle.y)
b = math.sqrt((Px - Cx)**2 + (Py - Cy)**2)
theta = math.acos(circleobstacle.radius / b)
d = math.atan2(Py - Cy, Px - Cx)
d1 = d + theta
d2 = d - theta
T1x = Cx + circleobstacle.radius * math.cos(d1)
T1y = Cy + circleobstacle.radius * math.sin(d1)
T2x = Cx + circleobstacle.radius * math.cos(d2)
T2y = Cy + circleobstacle.radius * math.sin(d2)
newestbvector = [self.posvector[0] - T1x, self.posvector[1], T1y]
multiplythemagain = newestbvector.normalize().dot(newvector.normalize())
b_angleinradian = math.acos(multiplythemagain)
newestcvector = [self.posvector[0] - T2x, self.posvector[1], T2y]
multiplythemagain = newestcvector.normalize().dot(newvector.normalize())
c_angleinradian = math.acos(multiplythemagain)
if(a_angleinradian < b_angleinradian and a_angleinradian < c_angleinradian):
#STEER THE BOID AWAY FROM TEH OBSTACLE BY SOME ANGLE
#MAYBE CAN CHANGE VELOCITY BY SMALL ANGLE AND THEN RERUN ALL OF THE ABOVE CHECKING CODE UNTIL NO MORE COLLISION
self.velvector = self.velvector.rotate(1)
else:
colliding = True
#RETURN THE NEW VELOCITY VECTOR.
return self.velvector
现在我将解释我的方法:为了避开障碍物,我首先确定如果 boid 继续沿当前方向移动,它是否会与它发生碰撞。为此,我计算了三个角度。角 a 是速度与连接 boid 到障碍物中心的矢量之间的角度,角 b 和 c 是从 boid 到圆的两条切线与连接 boid 的矢量之间的角度 do障碍物的中心。
下面是我的简单障碍类:
import pygame
class CircularObstacle():
def __init__(self, x, y, radius): #MAYBE ADD A SIZE
self.x = x
self.y = y
self.radius = radius
我计算圆切线的方法是使用此链接中的算法: Find tangent points in a circle from a point
要么我的整个想法是错误的,要么实施是错误的。也许我什至不应该改变速度矢量?我的孩子们刚刚通过障碍物,他们的行为变化为 0。另外,我知道旋转直到不发生碰撞的想法是错误的,因为这没有考虑到 boid 所面对的方向(因此它们可能以效率较低的方向旋转),但是现在这个问题更小(尽管我当然欢迎任何帮助)。