Sneh P
Sneh P

Reputation: 73

Attempting to bounce off window wall with Turtle

The program works but when it hits a wall the turtle undo's the last step and tries again. However, it keeps inputting the same forward distance and angle causing it to move in the same path in a loop. Is there a way to stop the turtle from taking the same value again?

from turtle import Turtle, Screen
import random

def createTurtle(color, width):
    tempName = Turtle("arrow")
    tempName.speed("fastest")
    tempName.color(color)
    tempName.width(width)
    return tempName

def inScreen(screen, turt):

    x = screen.window_width() / 2
    y = screen.window_height() / 2

    turtleX, turtleY = turt.pos()

    if not (-x < turtleX < x) and (-y < turtleY < y):
        return False
    return True

def moveTurtle(screen, turt):

    while True:
        while inScreen(screen, turt):
            turt.fd(random.randrange(100))
            turt.left(random.randrange(360))
        if (inScreen(screen, turt) == False):
            turt.undo()
            continue

wn = Screen()
alpha = createTurtle("red", 3)
moveTurtle(wn, alpha)
wn.exitonclick()

Upvotes: 0

Views: 251

Answers (2)

cdlane
cdlane

Reputation: 41872

My belief is that the problem with your code is this logic:

while inScreen(screen, turt):
    turt.fd(random.randrange(100))
    turt.left(random.randrange(360))
if (inScreen(screen, turt) == False):
    turt.undo()

When you invoke undo(), you're only undoing the last thing that happened, so you're undoing the left() but not the fd() (forward). On error you keep going further and further off screen and take longer to get back. If we undo both operations (two undo() calls), or reverse the order of operations and only undo the forward, then your random motion will correct itself much faster. No need to adjust the heading.

Here's a rework of your code to fix the above, and eliminate the while True: logic which doesn't belong in an event-driven program and keeps exitonclick() from working correctly:

from turtle import Turtle, Screen
import random

def createTurtle(color, width):
    turtle = Turtle('arrow')
    turtle.speed('fastest')
    turtle.color(color)
    turtle.width(width)

    return turtle

def inScreen(screen, turtle):

    x = screen.window_width() / 2
    y = screen.window_height() / 2

    turtleX, turtleY = turtle.pos()

    return (-x < turtleX < x) and (-y < turtleY < y)

def moveTurtle():

    turtle.left(random.randrange(360))
    turtle.forward(random.randrange(100))

    if not inScreen(screen, turtle):
        turtle.undo()  # undo forward()

    screen.ontimer(moveTurtle, 50)

screen = Screen()
turtle = createTurtle('red', 3)
moveTurtle()
screen.exitonclick()

Note that you can now click on the screen at any time to exit. With your original code, clicking on the screen did nothing on my system.

Upvotes: 1

Karl
Karl

Reputation: 1714

I do not think that it keeps moving in the same path. I tried running your code and it keeps giving the turtle a new forward amount and rotation. If you wait long enough it will eventually move from that spot.

The reason it appears that it is not moving in the spot is that it keeps attempting to go to a new spot, but it has a very high chance of picking a random value which puts the turtle outside the screen bounds again.

I would maybe guide the turtle to the opposite angle direction of the bounds if it goes outside the bounds because right now it is just repeatedly choosing random values.

Upvotes: 1

Related Questions