【问题标题】:How to bounce 2 turtles if both are touching each other如果两只乌龟都互相接触,如何弹跳
【发布时间】:2019-04-03 01:35:33
【问题描述】:

我正在尝试制作一个弹跳球模拟器。我需要一些帮助来尝试让球在它们接触时相互反弹,就像如果它们接触到球,它们会向另一个方向反弹。

我试过这样做:

def is_collided_with(a):
    for ball in balls:
        if abs(a.xcor() - ball.xcor()) < 3 and abs(a.ycor() - ball.ycor()) < 3:
            a.dx *= -1
            ball.dx *= -1
            a.dy *= -1
            ball.dy *= -1

while True:
    ... other code
    [is_collided_with(ball) for ball in balls]

但球似乎没有相互反弹。你能帮帮我吗?

代码:

import turtle
import random
import time

wn = turtle.Screen()
wn.bgcolor("black")
wn.tracer(0)

balls = []
numOfBalls = len(balls)

for _ in range(10):
    balls.append(turtle.Turtle())

colors = ["yellow", "gold", "orange", "red", "maroon", "violet", "magenta", "purple", "navy", "blue", "skyblue", "cyan", "turquoise", "lightgreen", "green", "darkgreen", "chocolate", "brown", "black", "gray", "white"]

for ball in balls:
    ball.shape("circle")
    ball.color(random.choice(colors))
    ball.penup()
    ball.speed(0)
    x = random.randint(-290, 290)
    y = random.randint(200, 400)
    ball.goto(x, y)
    ball.dy = 0
    ball.dx = random.randint(-3, 3)

gravity = 0.1

def addBall():
    balls.append(turtle.Turtle())
    balls[-1].shape("circle")
    balls[-1].color(random.choice(colors))
    balls[-1].penup()
    balls[-1].speed(0)
    x = random.randint(-290, 290)
    y = random.randint(200, 400)
    balls[-1].goto(x, y)
    balls[-1].dy = 0
    balls[-1].dx = random.randint(-3, 3)

def removeBall():
    balls[-1].reset()
    balls.pop()

def reload():
    for ball in balls:
        ball.shape("circle")
        ball.color(random.choice(colors))
        ball.penup()
        ball.speed(0)
        x = random.randint(-290, 290)
        y = random.randint(200, 400)
        ball.goto(x, y)
        ball.dy = 0
        ball.dx = random.randint(-3, 3)

_tick2_frame = 0
_tick2_fps = 20000000
_tick2_t0 = time.time()

def tick(fps=60):
    global _tick2_frame,_tick2_fps,_tick2_t0
    n = _tick2_fps/fps
    _tick2_frame += n
    while n>0: n-=1
    if time.time()-_tick2_t0>1:
        _tick2_t0 = time.time()
        _tick2_fps = _tick2_frame
        _tick2_frame=0

def is_collided_with(a):
    for ball in balls:
        if abs(a.xcor() - ball.xcor()) < 3 and abs(a.ycor() - ball.ycor()) < 3:
            a.dx *= -1
            ball.dx *= -1
            a.dy *= -1
            ball.dy *= -1


turtle.onkey(addBall, "a")
turtle.onkey(removeBall, "p")
turtle.onkey(reload, "r")
turtle.onkey(turtle.bye, "q")
turtle.listen()

while True:
    wn.update()
    numOfBalls = len(balls)
    if numOfBalls > 1:
        wn.title(str(numOfBalls) + ' Bouncing Balls')
    elif numOfBalls == 1:
        wn.title(str(numOfBalls) + ' Bouncing Ball')        
    elif numOfBalls == 0:
        wn.title(str(numOfBalls) + ' Bouncing Balls')
    else:
        wn.title('NaN Bouncing Balls')        

    for ball in balls:
        ball.dy -= gravity
        ball.sety(ball.ycor() + ball.dy)

        ball.setx(ball.xcor() + ball.dx)

        if ball.xcor() > 450 or ball.xcor() < -450:
            ball.dx *= -1

        if ball.ycor() < -300:
            ball.sety(-300)
            ball.dy *= -1

    [is_collided_with(ball) for ball in balls]

    tick(60)

turtle.listen()
turtle.mainloop()

【问题讨论】:

    标签: python python-3.x turtle-graphics


    【解决方案1】:

    我相信这是问题所在:

    [is_collided_with(ball) for ball in balls]
    
    def is_collided_with(a):
        for ball in balls:
            if abs(a.xcor() - ball.xcor()) < 3 and abs(a.ycor() - ball.ycor()) < 3:
                a.dx *= -1
                ball.dx *= -1
                a.dy *= -1
                ball.dy *= -1
    

    您正在检查每个球与其他球。如果它们发生碰撞,则仅将 dxdy 乘以 -1。但是如果 A 与 B 发生碰撞,则 B 与 A 发生碰撞,因此您的逻辑会触发 两次,从而有效地撤消自身!而且你不检查 A 和 B 是否是同一个球,这总是碰撞!

    以下是我对您的代码的修改和简化。它并不完美,但我相信你会得到更多你正在寻找的球碰撞和反弹效果:

    from turtle import Screen, Turtle
    from random import choice, randint
    
    BALL_DIAMETER = 40
    WIDTH, HEIGHT = 600, 600
    
    COLORS = ['yellow', 'gold', 'orange', 'red', 'maroon', 'violet', 'magenta', 'purple', 'navy', 'blue', 'skyblue', 'cyan', 'turquoise', 'lightgreen', 'green', 'darkgreen', 'chocolate', 'brown', 'gray', 'white']
    
    INITIAL_BALLS = 8
    
    GRAVITY = 0.1
    
    CURSOR_SIZE = 20
    
    def addBall():
        ball = Turtle('circle')
        ball.shapesize(BALL_DIAMETER / CURSOR_SIZE)
        ball.color(choice(COLORS))
        ball.penup()
        ball.speed('fastest')
        x, y = randint(BALL_DIAMETER - WIDTH/2, WIDTH/2 - BALL_DIAMETER), randint(BALL_DIAMETER - HEIGHT/2, HEIGHT/2 - BALL_DIAMETER)
        ball.goto(x, y)
        ball.dy = 0
        ball.dx = randint(-3, 3)
    
        balls.append(ball)
    
        numOfBalls = len(balls)
    
        if numOfBalls == 1:
            screen.title(str(numOfBalls) + " Bouncing Ball")
        else:
            screen.title(str(numOfBalls) + " Bouncing Balls")
    
    def removeBall():
        balls.pop().hideturtle()
    
        numOfBalls = len(balls)
    
        if numOfBalls == 0 or numOfBalls > 1:
            screen.title(str(numOfBalls) + " Bouncing Balls")
        else:
            screen.title(str(numOfBalls) + " Bouncing Ball")
    
    def reload():
        for ball in balls:
            ball.color(choice(COLORS))
            ball.penup()
            x, y = randint(BALL_DIAMETER - WIDTH/2, WIDTH/2 - BALL_DIAMETER), randint(BALL_DIAMETER - HEIGHT/2, HEIGHT/2 - BALL_DIAMETER)
            ball.goto(x, y)
            ball.dy = 0
            ball.dx = randint(-3, 3)
    
    def is_collided_with(other):
        for ball in balls:
            if ball != other and ball.distance(other) < BALL_DIAMETER:
                other.dx *= -1
                ball.dx *= -1
                other.dy *= -1
                ball.dy *= -1
    
    screen = Screen()
    screen.setup(WIDTH, HEIGHT)
    screen.bgcolor('black')
    screen.tracer(False)
    
    balls = []
    
    for _ in range(INITIAL_BALLS):
        addBall()
    
    screen.onkey(addBall, 'a')
    screen.onkey(removeBall, 'p')
    screen.onkey(reload, 'r')
    screen.onkey(screen.bye, 'q')
    
    screen.listen()
    
    def tick():
        for ball in balls:
            ball.dy -= GRAVITY
    
            ball.sety(ball.ycor() + ball.dy)
    
            ball.setx(ball.xcor() + ball.dx)
    
            if ball.ycor() < -HEIGHT/2:
                ball.sety(-HEIGHT/2)
                ball.dy *= -1
    
            if ball.xcor() > WIDTH/2 or ball.xcor() < -WIDTH/2:
                ball.dx *= -1
    
            is_collided_with(ball)
    
        screen.update()
        screen.ontimer(tick, 60)
    
    tick()
    screen.mainloop()
    

    希望这将为您提供足够的工作环境来完善球相互弹跳的细节。

    【讨论】:

    • 我没想到代码会撤销它的工作!太感谢了。现在我在打电话,所以我无法检查它的工作情况。当我回家时,我会检查。谢谢!
    猜你喜欢
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    • 2022-11-19
    • 1970-01-01
    • 1970-01-01
    • 2013-05-29
    • 2014-10-16
    • 1970-01-01
    相关资源
    最近更新 更多