Python : TclError: invalid command name ".!canvas"

Viewed 72

I am writing a custom game to learn python. When I am running the game and I am testing the bugs there is no crash but after I close the window, sometimes appear this error

TclError: invalid command name ".!canvas" 

sometimes does not and if this error code appears I have to reopen a new console otherwise the next run will crush and automatically restarting the console. How could I prevent this?

Here is all my code so far :

"""
Created on Thu Jul  8 18:34:52 2021

@author: Rudolf
"""

import turtle
import random
import time

#képernyő
wn = turtle.Screen()
wn.title("asd")
wn.bgcolor("black")
wn.setup(width=800, height=600)
wn.tracer(0,0)
#turtle.register_shape("asd.gif")

#bullet
bullet = turtle.Turtle()
bullet.speed(0)
bullet.color("blue")
bullet.shape("square")
bullet.shapesize(stretch_wid=1,stretch_len=1)
bullet.penup()
bullet.goto(1000,1000)
bullet.dx = 20

#vonal
vonal = turtle.Turtle()
vonal.speed(0)
vonal.color("white")
vonal.shape("square")
vonal.penup()
vonal.shapesize(stretch_wid=40,stretch_len=0.35)
vonal.goto(-3.5,0)

#első player
testone = turtle.Turtle()
testone.speed(0)
testone.color("white")
testone.shape("square")
testone.penup()
testone.shapesize(stretch_wid=3,stretch_len=3)
testone.goto(-200, 0)

#második player
testtwo = turtle.Turtle()
testtwo.speed(0)
testtwo.color("white")
testtwo.shape("square")
testtwo.penup()
testtwo.shapesize(stretch_wid=3,stretch_len=3)
testtwo.goto(200, 0)

#ammo
ammoone = turtle.Turtle()
ammoone.speed(0)
ammoone.color("red")
ammoone.shape("circle")
ammoone.penup()
ammoone.shapesize(stretch_wid=2,stretch_len=2)
ammoone.goto(random.randint(-380,-10),random.randint(-280,280))

#pont
pont = turtle.Turtle()
pont.speed(0)
pont.shape("square")
pont.color("white")
pont.hideturtle()
pont.penup()
pont.goto(0, -260)
pont.write("pont : 0  pont : 0", align="center", font=("Courier", 24, "normal"))

#ammo count
ammo = turtle.Turtle()
ammo.color("white")
ammo.shape("square")
ammo.penup()
ammo.hideturtle()
ammo.goto(0, 260)
ammo.write("Player 1 Ammo : 0 Player 2 Ammo : 0",align = "center", font = ("Courier", 24,"normal"))

a = 0
b = 0
c = 0
d = 0

#1-es player irányitás
def up():
        height = 300
        move = 80
        y = testone.ycor()
        if y < height :
            if y + move > height - 19:
                y = height - 19
                testone.sety(y)
            else:
                y += move
                testone.sety(y)
    
def down():
        height = -300
        move = 80 
        y = testone.ycor()
        if y > height :
            if y - move < height + 29:
                y = height + 29
                testone.sety(y)
            else:
                y -= move
                testone.sety(y)   

def left():
        width = -400
        move = 80 
        a = 22
        x = testone.xcor()
        if x > width :
            if x - move < width + a:
                x = width + a
                testone.setx(x)
            else:
                x -= move
                testone.setx(x)

def right():
        width = 0
        move = 80 
        a = 29
        x = testone.xcor()
        if x < width :
            if x + move > width - a:
                x = width -a
                testone.setx(x)
            else:
                x += move
                testone.setx(x)
                
def fire():
        global a
        if bullet.xcor() > 1000 and bullet.ycor() == 1000:
           
            if a > 0:
                a -= 1
                bullet.goto(testone.xcor(),testone.ycor())
    
#2-es player irányitás               
def uptwo():
        height = 300
        move = 80
        y = testtwo.ycor()
        if y < height :
            if y + move > height - 19:
                y = height - 19
                testtwo.sety(y)
            else:
                y += move
                testtwo.sety(y)
    
def downtwo():
        height = -300
        move = 80 
        y = testtwo.ycor()
        if y > height :
            if y - move < height + 29:
                y = height + 29
                testtwo.sety(y)
            else:
                y -= move
                testtwo.sety(y)   

def lefttwo():
        width = 0
        move = 80 
        a = 22
        x = testtwo.xcor()
        if x > width :
            if x - move < width + a:
                x = width + a
                testtwo.setx(x)
            else:
                x -= move
                testtwo.setx(x)

def righttwo():
        width = 400
        move = 80 
        a = 29
        x = testtwo.xcor()
        if x < width :
            if x + move > width - a:
                x = width -a
                testtwo.setx(x)
            else:
                x += move
                testtwo.setx(x)
    
wn.listen()   
wn.onkeypress(up,"w")
wn.onkeypress(down,"s")
wn.onkeypress(left,"a")
wn.onkeypress(right,"d")

wn.onkeypress(uptwo,"Up")
wn.onkeypress(downtwo,"Down")
wn.onkeypress(lefttwo,"Left")
wn.onkeypress(righttwo,"Right")

run = True

while run:
    wn.update()
    bullet.setx(bullet.xcor() + bullet.dx)

    if ammoone.xcor() + 30 > testone.xcor() - 30 and ammoone.xcor() - 30 < testone.xcor() + 30 and ammoone.ycor() + 30 > testone.ycor() - 30 and ammoone.ycor() - 30 < testone.ycor() + 30:
        
        a += 1
        
        ammoone.goto(random.randint(-380,-10),random.randint(-280,280))
        ammo.clear()
        ammo.write("Player 1 Ammo : {} Player 2 Ammo : {}".format(a, b),align = "center", font = ("Courier", 24,"normal"))
        
    if bullet.xcor() > 1000 and bullet.ycor() == 1000:
        wn.onkeypress(fire,"q")
    
    if testtwo.xcor() + 30 > bullet.xcor() - 30 and testtwo.xcor() - 30 < bullet.xcor() + 30 and testtwo.ycor() + 30 > bullet.ycor() - 30 and testtwo.ycor() - 30 < bullet.ycor() + 30:
                 
        c += 1
        bullet.goto(1000,1000)
    
    if bullet.xcor() > 400 and bullet.xcor() < 500:
        bullet.goto(1000,1000)
                            
    ammo.clear()
    ammo.write("Player 1 Ammo : {} Player 2 Ammo : {}".format(a, b),align = "center", font = ("Courier", 24,"normal"))   
    pont.clear()
    pont.write("pont : {}  pont : {}".format(c, d), align="center", font=("Courier", 24, "normal"))

    wn.update()

wn.exitonclick()
2 Answers

You can replace your infinite loop with a function that will use the wn.ontimer function, which will be called continuously with the wn.mainloop() function, from:

run = True

while run:
    wn.update()
    bullet.setx(bullet.xcor() + bullet.dx)

    if ammoone.xcor() + 30 > testone.xcor() - 30 and ammoone.xcor() - 30 < testone.xcor() + 30 and ammoone.ycor() + 30 > testone.ycor() - 30 and ammoone.ycor() - 30 < testone.ycor() + 30:
        
        a += 1
        
        ammoone.goto(random.randint(-380,-10),random.randint(-280,280))
        ammo.clear()
        ammo.write("Player 1 Ammo : {} Player 2 Ammo : {}".format(a, b),align = "center", font = ("Courier", 24,"normal"))
        
    if bullet.xcor() > 1000 and bullet.ycor() == 1000:
        wn.onkeypress(fire,"q")
    
    if testtwo.xcor() + 30 > bullet.xcor() - 30 and testtwo.xcor() - 30 < bullet.xcor() + 30 and testtwo.ycor() + 30 > bullet.ycor() - 30 and testtwo.ycor() - 30 < bullet.ycor() + 30:
                 
        c += 1
        bullet.goto(1000,1000)
    
    if bullet.xcor() > 400 and bullet.xcor() < 500:
        bullet.goto(1000,1000)
                            
    ammo.clear()
    ammo.write("Player 1 Ammo : {} Player 2 Ammo : {}".format(a, b),align = "center", font = ("Courier", 24,"normal"))   
    pont.clear()
    pont.write("pont : {}  pont : {}".format(c, d), align="center", font=("Courier", 24, "normal"))

    wn.update()

to:

def run():
    wn.update()
    bullet.setx(bullet.xcor() + bullet.dx)

    if ammoone.xcor() + 30 > testone.xcor() - 30 and ammoone.xcor() - 30 < testone.xcor() + 30 and ammoone.ycor() + 30 > testone.ycor() - 30 and ammoone.ycor() - 30 < testone.ycor() + 30:

        a += 1

        ammoone.goto(random.randint(-380,-10),random.randint(-280,280))
        ammo.clear()
        ammo.write("Player 1 Ammo : {} Player 2 Ammo : {}".format(a, b),align = "center", font = ("Courier", 24,"normal"))

    if bullet.xcor() > 1000 and bullet.ycor() == 1000:
        wn.onkeypress(fire,"q")

    if testtwo.xcor() + 30 > bullet.xcor() - 30 and testtwo.xcor() - 30 < bullet.xcor() + 30 and testtwo.ycor() + 30 > bullet.ycor() - 30 and testtwo.ycor() - 30 < bullet.ycor() + 30:

        c += 1
        bullet.goto(1000,1000)

    if bullet.xcor() > 400 and bullet.xcor() < 500:
        bullet.goto(1000,1000)

    ammo.clear()
    ammo.write("Player 1 Ammo : {} Player 2 Ammo : {}".format(a, b),align = "center", font = ("Courier", 24,"normal"))   
    pont.clear()
    pont.write("pont : {}  pont : {}".format(c, d), align="center", font=("Courier", 24, "normal"))

    wn.update()
    wn.ontimer(run)

run()
mainloop()

i did it,made global variables,and now the program does this error : TclError: can't invoke "bind" command: application has been destroyed ,but it does exactly the same,have to restart the console otherwise it carshes at the next run

Related