TurtleGraphics Python: 如何让海龟在墙上反弹?

1 投票
2 回答
5719 浏览
提问于 2025-04-15 14:29

我在尝试制作一个真实的反弹功能,也就是当小海龟碰到墙壁时,会按照相应的角度反弹。我的代码是这样的:

def bounce(num_steps, step_size, initial_heading):
   turtle.reset()
   top = turtle.window_height()/2
   bottom = -top
   right = turtle.window_width()/2
   left = -right

   turtle.left(initial_heading)
   for step in range(num_steps):
      turtle.forward(step_size)
      x, y = turtle.position()
      if left <= x <= right and bottom <= y <= top:
         pass
      else:
         turtle.left(180-2 * (turtle.heading()))

这个代码在左右墙壁的反弹效果很好,但我不知道怎么让它在上下墙壁碰撞时也能正确反弹。有没有什么建议?

2 个回答

0

你好,

你的问题似乎是你在计算左右墙壁时,使用的三角函数和计算上下墙壁时是一样的。其实用一张纸和一支铅笔就可以算出需要的偏移量。

def inbounds(limit, value):
    'returns boolean answer to question "is turtle position within my axis limits"'
    return -limit < value * 2 < limit

def bounce(num_steps, step_size, initial_heading):
    '''given the number of steps, the size of the steps 
        and an initial heading in degrees, plot the resultant course
        on a turtle window, taking into account elastic collisions 
        with window borders.
    '''

    turtle.reset()
    height = turtle.window_height()
    width = turtle.window_width()
    turtle.left(initial_heading)

    for step in xrange(num_steps):
        turtle.forward(step_size)
        x, y = turtle.position()

        if not inbounds(height, y):
            turtle.setheading(-turtle.heading())

        if not inbounds(width, x):
            turtle.setheading(180 - turtle.heading())

我使用了 setheading 函数和一个辅助函数(inbounds)来进一步说明这段代码的意图。给你的代码加上一些说明文字也是个好习惯(前提是这些说明要准确!)

关于 xrange 的使用,可能会有所不同,因为在 Python 3.0 及以上版本中,它被简单地改名为 range

1

试试这样做:

if not (left <= x <= right):
    turtle.left(180 - 2 * turtle.heading())
elif not (bottom <= y <= top):
    turtle.left(-2 * turtle.heading())
else:
    pass

我的Python语法有点生疏,抱歉 :P。不过,水平翻转和垂直翻转的数学计算有点不同。

补充说明

我怀疑你遇到的问题是你的乌龟(turtle)指向上方,并且卡在了上面的墙壁上。这会导致它一直翻转下去。你可以尝试添加以下条件:

if (x <= left and 90 <= turtle.heading() <= 270) or (right <= x and not 90 <= turtle.heading() <= 270):
    turtle.left(180 - 2 * turtle.heading())
elif (y <= bottom and turtle.heading() >= 180) or (top <= y and turtle.heading <= 180):
    turtle.left(-2 * turtle.heading())
else:
    pass

如果这样能解决问题,那可能你的代码其他地方还有bug。处理边界情况是比较棘手的。我假设turtle.heading()总是返回0到360之间的值——如果不是,那就更难处理了。

撰写回答