在python中检测多个turtle对象之间的碰撞

2024-09-29 18:47:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我是维基百科的医学编辑(几乎没有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()

Tags: forifiswithrandomrandintturtledy
1条回答
网友
1楼 · 发布于 2024-09-29 18:47:48

问题在于这一行:

if is_collided_with(ball, ball):

您两次传递同一个ball对象,将其视为分开球。基本上,对于球列表中的每个球,if语句都会说“这个球是否与自身碰撞?”——这对于模拟的每个帧都是正确的。因此,您总是输入if语句的主体,并翻转当前球的x方向和y方向向量,这会导致每个球都在适当的位置振荡

简单的解决方案包括将当前球与模拟中的所有其他球进行比较。我说“幼稚”是因为,虽然这确实有效,但对于更多的球来说,它变得非常低效和缓慢。更复杂的解决方案将使用某种空间分割技术(如四叉树)来显著提高性能(这只通过比较可能靠近的球来实现,而所有其他远离的球都被剔除,不考虑进行比较)

在您的情况下,只要球的数量很小,简单的解决方案就可以正常工作。它看起来像这样(注意嵌套的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)都需要/应该翻转。想象一个场景,两个球在同一方向上移动,但速度略有不同,前面的球比后面的球慢(后面的球正在追赶)——一旦它们碰撞,翻转两个方向向量分量是不正确的

相关问题 更多 >

    热门问题