Home > Net >  Python Turtle becomes unresponsive and hangs after using a while loop
Python Turtle becomes unresponsive and hangs after using a while loop

Time:11-01

I'm trying to make a program that is essentially an etchasketck, with some minor tweaks for my school project(the required use of a main function, wasd as movement controls, and q to quit the program and p to pick up or drop down the turtle pen). I was testing this code in trinket.io and it was working fine. You can see it working there with this link: https://trinket.io/python/99fd3ec305. However, when I go to run it from pycharm, cmd, or the python IDLE, it always leaves the turtle hanging and unresponsive. I get no errors, just the turtle to pop up for a few seconds, then it hangs, and I'm unable to do anything. Here's my code:

import sys
import turtle

arg_len = len(sys.argv)

# store length of arguments

if arg_len < 3:
    print("Too less arguments, using default values..")
    WIDTH = 200
    HEIGHT = 200
else:
    WIDTH = int(sys.argv[1])
    HEIGHT = int(sys.argv[2])

screen = turtle.Screen()
screen.setup(WIDTH, HEIGHT)
# create a turtle instance
t = turtle.Turtle()
t.speed(0)
# slow down the turtle
# declare flags
move = False
exit_flag = False


def up():
    global move
    move = True
    t.setheading(90)


def down():
    global move
    move = True
    t.setheading(270)


def left():
    global move
    move = True
    t.setheading(180)


def right():
    global move
    move = True
    t.setheading(0)


# toggle pen up and down
def toggle_pen():
    if t.isdown():
        t.penup()
    else:
        t.pendown()


# set exit flag
def quit_program():
    global exit_flag
    exit_flag = True


def check_border():
    if t.xcor() == WIDTH / 2:
        t.penup()
        t.setx(-WIDTH / 2)
    elif t.xcor() == -WIDTH / 2:
        t.penup()
        t.setx(WIDTH / 2)
    if t.ycor() == HEIGHT / 2:
        t.penup()
        t.sety(-HEIGHT / 2)
    elif t.ycor() == -HEIGHT / 2:
        t.penup()
        t.sety(HEIGHT / 2)


def listen_keys():
    screen.listen()
    screen.onkey(up, "w")
    screen.onkey(down, "s")
    screen.onkey(left, "a")
    screen.onkey(right, "d")
    screen.onkey(toggle_pen, "p")
    screen.onkey(quit_program, "q")


# main loop
def main():
    listen_keys()
    while not exit_flag:
        global move
        if move:
            t.forward(0.5)
            screen.update()
        check_border()
    else:
        t.done()

main()

I'm using python 3.10, and I mainly use pycharm for the running.

I was trying to get the turtle to move indefinitly without user input after the first user input, I was going to achieve this with the while loop, but it just leaves my program unresponsive. Can anyone tell me what's wrong that I'm not seeing?

CodePudding user response:

You've effectively put a while True: loop in an event-driven program where one should never be used. If I were writing this for the command line, with the constraints listed, I might go about it this way (dropping command line processing for example simplicity):

from turtle import Screen, Turtle

WIDTH, HEIGHT = 200, 200

def up():
    turtle.setheading(90)
    start_motion()

def down():
    turtle.setheading(270)
    start_motion()

def left():
    turtle.setheading(180)
    start_motion()

def right():
    turtle.setheading(0)
    start_motion()

def toggle_pen():
    if turtle.isdown():
        turtle.penup()
    else:
        turtle.pendown()

def quit_program():
    screen.bye()

def check_border():
    x, y = turtle.position()

    if x >= WIDTH / 2:
        turtle.penup()
        turtle.setx(-WIDTH / 2)
    elif x <= -WIDTH / 2:
        turtle.penup()
        turtle.setx(WIDTH / 2)

    if y >= HEIGHT / 2:
        turtle.penup()
        turtle.sety(-HEIGHT / 2)
    elif y <= -HEIGHT / 2:
        turtle.penup()
        turtle.sety(HEIGHT / 2)

def main():
    screen.onkey(up, 'w')
    screen.onkey(down, 's')
    screen.onkey(left, 'a')
    screen.onkey(right, 'd')

    screen.onkey(toggle_pen, 'p')
    screen.onkey(quit_program, 'q')

    screen.listen()
    screen.mainloop()

def move():
    turtle.forward(1)

    check_border()

    screen.ontimer(move, 25)

moving = False

def start_motion():
    global moving

    if not moving:
        moving = True
        move()

screen = Screen()
screen.setup(WIDTH, HEIGHT)

turtle = Turtle()
turtle.speed('fastest')

main()

See if this still works with trinket.io, IDLE and PyCharm, or if it can be made to do so.

  • Related