检测 python 中许多海龟对象之间的碰撞
Detecting collision between many turtle objects in python
我是维基百科的一名医学编辑(python 经验几乎为零),我们正在尝试模拟社交距离的影响。我试图让一堆圆圈在正方形中弹跳 space。我让它们从墙上弹起,但我不确定如何检测球之间的碰撞。我创建了一个定义 is_collided_with 但是行
if is_collided_with(ball, ball):
ball.dy *=-1
ball.dx *=-1
冻结一切。如果你删除它,你可以看到运动(根据我的理解,速度可能因系统而异)。最终目标是改变颜色,从健康到传染,再到治愈,并展示社交距离如何与不同数量的人一起工作。
这是完整的代码,
#bouncing balls
import turtle
import random
wn = turtle.Screen()
wn.bgcolor("white")
wn.title("ball simulator")
wn.tracer(0)
balls = []
for _ in range(10):
balls.append(turtle.Turtle())
for ball in balls:
ball.shape("circle")
ball.color("red")
ball.penup()
ball.speed(1)
x = random.randint(-290,290)
y = random.randint(-290,290)
ball.goto(x, y)
ball.dy = (random.randint(-3, 3))/5+.1
ball.dx = (random.randint(-3, 3))/5+.1
def is_collided_with(a, b):
return abs(a.xcor() - b.xcor()) < 10 and abs(a.ycor() - b.ycor()) < 10
while True:
wn.update()
for ball in balls:
ball.sety(ball.ycor() + ball.dy)
ball.setx(ball.xcor() + ball.dx)
#check for a bounce
if is_collided_with(ball, ball):
ball.dy *=-1
ball.dx *=-1
if ball.ycor() <-300:
ball.dy *=-1
if ball.ycor() >+300:
ball.dy *=-1
if ball.xcor() >+300:
ball.dx *=-1
if ball.xcor() <-300:
ball.dx *=-1
wn.mainloop()
问题出在这一行:
if is_collided_with(ball, ball):
您两次传入同一个 ball
对象,将其视为分开的球。基本上,对于您的球列表中的每个球,if 语句都在说 "is this ball colliding with itself?" - 这对于模拟的每一帧都始终为真。因此,您总是进入 if 语句的主体,并翻转当前球的 x 和 y 方向向量,这导致每个球都在原地摆动。
天真的解决方案涉及将当前球与模拟中的所有其他球进行比较。我说 "naive" 是因为,虽然这确实有效,但对于更多的球来说,它变得非常低效和缓慢。一个更复杂的解决方案是使用某种 space 分区技术,如四叉树来显着提高性能(这通过只比较有可能接近的球,而所有其他远离的球被剔除和不考虑比较)。
在你的情况下,只要球的数量少,天真的解决方案应该可以。它看起来像这样(注意嵌套的 for 循环):
while True:
wn.update()
for ball in balls:
ball.sety(ball.ycor() + ball.dy)
ball.setx(ball.xcor() + ball.dx)
for other_ball in balls:
if other_ball is ball:
# We are not interested in balls colliding with themselves.
# Skip the current iteration of the inner for-loop, and move on to the next ball
continue
if is_collided_with(ball, other_ball):
ball.dx *= -1
ball.dy *= -1
if ball.ycor() <-300:
ball.dy *=-1
if ball.ycor() >+300:
ball.dy *=-1
if ball.xcor() >+300:
ball.dx *=-1
if ball.xcor() <-300:
ball.dx *=-1
最后一件事,请记住,从技术上讲,仅仅因为两个球发生碰撞并不意味着它们的两个方向矢量分量(x 和 y)都需要/应该翻转。想象这样一种情况,两个球以相同的方向但速度略有不同,前面的球比后面的球慢(正在追赶)——一旦它们碰撞,翻转两个方向是不正确的-向量分量。
我是维基百科的一名医学编辑(python 经验几乎为零),我们正在尝试模拟社交距离的影响。我试图让一堆圆圈在正方形中弹跳 space。我让它们从墙上弹起,但我不确定如何检测球之间的碰撞。我创建了一个定义 is_collided_with 但是行
if is_collided_with(ball, ball):
ball.dy *=-1
ball.dx *=-1
冻结一切。如果你删除它,你可以看到运动(根据我的理解,速度可能因系统而异)。最终目标是改变颜色,从健康到传染,再到治愈,并展示社交距离如何与不同数量的人一起工作。
这是完整的代码,
#bouncing balls
import turtle
import random
wn = turtle.Screen()
wn.bgcolor("white")
wn.title("ball simulator")
wn.tracer(0)
balls = []
for _ in range(10):
balls.append(turtle.Turtle())
for ball in balls:
ball.shape("circle")
ball.color("red")
ball.penup()
ball.speed(1)
x = random.randint(-290,290)
y = random.randint(-290,290)
ball.goto(x, y)
ball.dy = (random.randint(-3, 3))/5+.1
ball.dx = (random.randint(-3, 3))/5+.1
def is_collided_with(a, b):
return abs(a.xcor() - b.xcor()) < 10 and abs(a.ycor() - b.ycor()) < 10
while True:
wn.update()
for ball in balls:
ball.sety(ball.ycor() + ball.dy)
ball.setx(ball.xcor() + ball.dx)
#check for a bounce
if is_collided_with(ball, ball):
ball.dy *=-1
ball.dx *=-1
if ball.ycor() <-300:
ball.dy *=-1
if ball.ycor() >+300:
ball.dy *=-1
if ball.xcor() >+300:
ball.dx *=-1
if ball.xcor() <-300:
ball.dx *=-1
wn.mainloop()
问题出在这一行:
if is_collided_with(ball, ball):
您两次传入同一个 ball
对象,将其视为分开的球。基本上,对于您的球列表中的每个球,if 语句都在说 "is this ball colliding with itself?" - 这对于模拟的每一帧都始终为真。因此,您总是进入 if 语句的主体,并翻转当前球的 x 和 y 方向向量,这导致每个球都在原地摆动。
天真的解决方案涉及将当前球与模拟中的所有其他球进行比较。我说 "naive" 是因为,虽然这确实有效,但对于更多的球来说,它变得非常低效和缓慢。一个更复杂的解决方案是使用某种 space 分区技术,如四叉树来显着提高性能(这通过只比较有可能接近的球,而所有其他远离的球被剔除和不考虑比较)。
在你的情况下,只要球的数量少,天真的解决方案应该可以。它看起来像这样(注意嵌套的 for 循环):
while True:
wn.update()
for ball in balls:
ball.sety(ball.ycor() + ball.dy)
ball.setx(ball.xcor() + ball.dx)
for other_ball in balls:
if other_ball is ball:
# We are not interested in balls colliding with themselves.
# Skip the current iteration of the inner for-loop, and move on to the next ball
continue
if is_collided_with(ball, other_ball):
ball.dx *= -1
ball.dy *= -1
if ball.ycor() <-300:
ball.dy *=-1
if ball.ycor() >+300:
ball.dy *=-1
if ball.xcor() >+300:
ball.dx *=-1
if ball.xcor() <-300:
ball.dx *=-1
最后一件事,请记住,从技术上讲,仅仅因为两个球发生碰撞并不意味着它们的两个方向矢量分量(x 和 y)都需要/应该翻转。想象这样一种情况,两个球以相同的方向但速度略有不同,前面的球比后面的球慢(正在追赶)——一旦它们碰撞,翻转两个方向是不正确的-向量分量。