I'm making a basic Turtle game where you go go through a maze and get to the cheese, there's an issue with my win condition though, I know what the problem is, it's that the project is attempting to run an input
when already expecting user input. I'm guessing that's because the win()
function gets called multiple times before the user actually responds. I've tried multiple ways of fixing this to no avail. Here's my code:
import turtle
import datetime
won = False
turtle.setup(800, 590)
mouse_l = "mouse_l.gif"
mouse_r = "mouse_r.gif"
mouse_u = "mouse_u.gif"
mouse_d = "mouse_d.gif"
map = "map.gif"
turtle.setup(800, 590)
turtle.tracer(0, 0)
turtle.delay(0)
FRAME_TIME = 5 # in ms
wn = turtle.Screen()
wn.bgpic(map)
wn.register_shape(mouse_d)
wn.register_shape(mouse_r)
wn.register_shape(mouse_l)
wn.register_shape(mouse_u)
wn.tracer(0, delay=0)
wn.delay(0)
player = turtle.Turtle()
player.speed(0)
player.penup()
player.shape(mouse_d)
start_time = datetime.datetime.now()
keys = {
"w": False,
"s": False,
"a": False,
"d": False
}
def check_win():
return player.ycor() < -230 and player.xcor() > 335
def win():
global won
global start_time
print("You won!")
won_time = datetime.datetime.now()
final_time = won_time.replace(microsecond=0) - start_time.replace(microsecond=0)
print(f"Your time was {final_time}")
if input("Do you want to play again? y/n ").lower() == "y":
won = False
player.goto(-352, 195)
start_time = datetime.datetime.now()
def movement():
global won
if keys["w"]:
player.seth(90)
player.fd(6)
if keys["s"]:
player.seth(270)
player.fd(6)
if keys["a"]:
player.seth(180)
player.fd(6)
if keys["d"]:
player.seth(0)
player.fd(6)
turtle.update()
won = check_win()
if won == True:
won = "winning"
return win()
return wn.ontimer(movement, FRAME_TIME)
def c_keys(key, value):
keys[key] = value
player.goto(-352, 195)
turtle.update()
movement()
wn.onkeypress(lambda: c_keys("w", True), "w")
wn.onkeyrelease(lambda: c_keys("w", False), "w")
wn.onkeypress(lambda: c_keys("s", True), "s")
wn.onkeyrelease(lambda: c_keys("s", False), "s")
wn.onkeypress(lambda: c_keys("a", True), "a")
wn.onkeyrelease(lambda: c_keys("a", False), "a")
wn.onkeypress(lambda: c_keys("d", True), "d")
wn.onkeyrelease(lambda: c_keys("d", False), "d")
wn.listen()
Any help is appreciated. Thanks!
EDIT 1: Addressing Johnny Mopp's comment (Rework win check in movement()
, tried a few ways, still getting the issue)
import turtle
import datetime
turtle.setup(800, 590)
prompting = False
mouse_l = "mouse_l.gif"
mouse_r = "mouse_r.gif"
mouse_u = "mouse_u.gif"
mouse_d = "mouse_d.gif"
map = "map.gif"
turtle.setup(800, 590)
turtle.tracer(0, 0)
turtle.delay(0)
FRAME_TIME = 5 # in ms
wn = turtle.Screen()
wn.bgpic(map)
wn.register_shape(mouse_d)
wn.register_shape(mouse_r)
wn.register_shape(mouse_l)
wn.register_shape(mouse_u)
wn.tracer(0, delay=0)
wn.delay(0)
player = turtle.Turtle()
player.speed(0)
player.penup()
player.shape(mouse_d)
start_time = datetime.datetime.now()
keys = {
"w": False,
"s": False,
"a": False,
"d": False
}
def won():
return player.ycor() < -230 and player.xcor() > 335
def play_again():
global start_time
global prompting
print("playing again", prompting)
if prompting:
return
prompting = True
print("You won!")
won_time = datetime.datetime.now()
final_time = won_time.replace(microsecond=0) - start_time.replace(microsecond=0)
print(f"Your time was {final_time}")
if input("Do you want to play again? y/n ").lower() == "y":
player.goto(-352, 195)
start_time = datetime.datetime.now()
def movement():
if keys["w"]:
player.seth(90)
player.fd(6)
if keys["s"]:
player.seth(270)
player.fd(6)
if keys["a"]:
player.seth(180)
player.fd(6)
if keys["d"]:
player.seth(0)
player.fd(6)
turtle.update()
if won():
return play_again()
return wn.ontimer(movement, FRAME_TIME)
def c_keys(key, value):
keys[key] = value
player.goto(-352, 195)
turtle.update()
movement()
wn.onkeypress(lambda: c_keys("w", True), "w")
wn.onkeyrelease(lambda: c_keys("w", False), "w")
wn.onkeypress(lambda: c_keys("s", True), "s")
wn.onkeyrelease(lambda: c_keys("s", False), "s")
wn.onkeypress(lambda: c_keys("a", True), "a")
wn.onkeyrelease(lambda: c_keys("a", False), "a")
wn.onkeypress(lambda: c_keys("d", True), "d")
wn.onkeyrelease(lambda: c_keys("d", False), "d")
wn.listen()
EDIT 2: Original error message
You won!
Your time was 0:00:03
Exception in Tkinter callback
Traceback (most recent call last):
File "/nix/store/2vm88xw7513h9pyjyafw32cps51b0ia1-python3-3.8.12/lib/python3.8/tkinter/__init__.py", line 1892, in __call__
return self.func(*args)
File "/nix/store/2vm88xw7513h9pyjyafw32cps51b0ia1-python3-3.8.12/lib/python3.8/tkinter/__init__.py", line 814, in callit
func(*args)
File "main.py", line 80, in movement
if won() and not play_again():
File "main.py", line 57, in play_again
if input("Do you want to play again? y/n ").lower() == "y":
RuntimeError: can't re-enter readline
CodePudding user response:
Try something like this:
def play_again():
global start_time
print("You won!")
won_time = datetime.datetime.now()
final_time = won_time.replace(microsecond=0) - start_time.replace(microsecond=0)
print(f"Your time was {final_time}")
if input("Do you want to play again? y/n ").lower() == "y":
player.goto(-352, 195)
start_time = datetime.datetime.now()
return True
else:
return False
def movement():
# Other stuff removed for brevity
#.......
if won() and not play_again():
return
return wn.ontimer(movement, FRAME_TIME)