我是维基百科的医学编辑(几乎没有python经验),我们正在尝试构建一个社交距离效应的模拟。我想让一堆圆圈在一个正方形的空间里反弹。我让它们从墙上弹下来,但我不确定如何检测球之间的碰撞。我已经创建了一个定义,但它与线冲突
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()
问题在于这一行:
您两次传递同一个
ball
对象,将其视为分开球。基本上,对于球列表中的每个球,if语句都会说“这个球是否与自身碰撞?”——这对于模拟的每个帧都是正确的。因此,您总是输入if语句的主体,并翻转当前球的x方向和y方向向量,这会导致每个球都在适当的位置振荡简单的解决方案包括将当前球与模拟中的所有其他球进行比较。我说“幼稚”是因为,虽然这确实有效,但对于更多的球来说,它变得非常低效和缓慢。更复杂的解决方案将使用某种空间分割技术(如四叉树)来显著提高性能(这只通过比较可能靠近的球来实现,而所有其他远离的球都被剔除,不考虑进行比较)
在您的情况下,只要球的数量很小,简单的解决方案就可以正常工作。它看起来像这样(注意嵌套的for循环):
最后一件事,请记住,从技术上讲,仅仅因为两个球碰撞并不意味着它们的方向向量分量(x和y)都需要/应该翻转。想象一个场景,两个球在同一方向上移动,但速度略有不同,前面的球比后面的球慢(后面的球正在追赶)——一旦它们碰撞,翻转两个方向向量分量是不正确的
相关问题 更多 >
编程相关推荐