So, I am trying to make a realistic bouncing function, where the turtle hits a wall and bounces off at the corresponding angle. My code looks like this:
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()))
So, this works for the side walls, but I don't get how to make it bounce correctly off the top/bottom. Any suggestions?
Try something like this:
if not (left <= x <= right):
turtle.left(180 - 2 * turtle.heading())
elif not (bottom <= y <= top):
turtle.left(-2 * turtle.heading())
else:
pass
My python syntax is a little rusty, sorry :P. But the math is a little different for a horizontal vs. a vertical flip.
EDIT:
I suspect that what is happening is your turtle is getting into a situation where it is pointing upwards and stuck above the top wall. That would lead it to just flip indefinitely. You could try adding the following conditions:
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
If that works, there is probably a bug elsewhere in your code. Edge handling is tricky to get right. I assume that turtle.heading() will always return something between 0 and 360 - if not then it will be even more tricky to get right.
Gday,
Your problem seems to be that you are using the same trigonometry to calculate the right and left walls, as you are the top and bottom. A piece of paper and a pencil should suffice to calculate the required deflections.
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())
I've used the setheading
function and a helper function (inbounds
) to further declare the intent of the code here. Providing some kind of doc-string is also good practice in any code that you write (provided the message it states is accurate!!)
Your mileage may vary on the use of xrange
, Python 3.0+ renames it to simply range
.
来源:https://stackoverflow.com/questions/1457332/turtlegraphics-python-bouncing-turtle-off-the-walls