简体   繁体   中英

Python tkinter and turtle errors after program stops

sorry to bother anyone but when I run my code (my first attempt at a real game) everything works fine, but then after I close it some errors print and I can't find anyone else with my problem. My files is called Space Invaders.py, I am using Pycharm (these errors also occur with the IDLE). This is my code:

import turtle
import math

print("------------Space Invaders - Python------------")
print("-------------GAME NOT YET COMPLETED------------")
print("This console is simply a status readout.")

wn = turtle.Screen()
wn.bgcolor("black")
wn.title("Space Invaders")


borderPen = turtle.Turtle()
borderPen.speed(0)
borderPen.color("white")
borderPen.penup()
borderPen.setposition(-400, -400)
borderPen.pendown()
borderPen.pensize(3)
for i in range(4):
    borderPen.fd(800)
    borderPen.lt(90)
borderPen.hideturtle()


player = turtle.Turtle()
player.setheading(90)
player.shape("triangle")
player.color("blue")
player.penup()
player.speed(0)
player.setposition(0, -350)


enemy = turtle.Turtle()
enemy.color("red")
enemy.shape("circle")
enemy.penup()
enemy.speed(0)
enemy.setposition(-300, 250)

movementStepE = 2
movementStepEY = -15
movementStepP = 5 


def move_left():
    x = player.xcor()
    new_x = x - movementStepP
    if new_x < -380:
        new_x = -380
    player.setx(new_x)


def move_right():
    x = player.xcor()
    new_x = x + movementStepP
    if new_x > 380:
        new_x = 380
    player.setx(new_x)


def distancepyth(x1, x2, y1, y2):
    pyth = math.sqrt((x1 - x2) ** 2) + (y1 - y2 ** 2)
    return(pyth)


turtle.listen()
turtle.onkeypress(move_left, "Left")

turtle.onkeypress(move_right, "Right")

new_y = 250  # 250
while True:

    x = enemy.xcor()
    y = enemy.ycor()
    new_x = x + movementStepE
    if new_x > 380:
        movementStepE = movementStepE * -1
        new_y = y + movementStepEY
        new_x = 380
    elif new_x < -380:
        movementStepE = movementStepE * -1
        new_y = y + movementStepEY
        new_x = -380
    enemy.setposition(new_x, new_y)

turtle.done()

print("-------PROGRAM TERMINATED INTENTIONALLY-------")

and these are the errors:

Traceback (most recent call last):
  File "C:/Users/Noname Antilabelson/PycharmProjects/Space Invaders Game/Code/Space Invaders.py", line 97, in <module>
    enemy.setposition(new_x, new_y)
  File "C:\Users\Noname Antilabelson\AppData\Local\Programs\Python\Python37\lib\turtle.py", line 1776, in goto
    self._goto(Vec2D(x, y))
  File "C:\Users\Noname Antilabelson\AppData\Local\Programs\Python\Python37\lib\turtle.py", line 3158, in _goto
    screen._pointlist(self.currentLineItem),
  File "C:\Users\Noname Antilabelson\AppData\Local\Programs\Python\Python37\lib\turtle.py", line 755, in _pointlist
    cl = self.cv.coords(item)
  File "<string>", line 1, in coords
  File "C:\Users\Noname Antilabelson\AppData\Local\Programs\Python\Python37\lib\tkinter\__init__.py", line 2469, in coords
    self.tk.call((self._w, 'coords') + args))]
_tkinter.TclError: invalid command name ".!canvas"

Sorry if I've done anything stupid, your help would be greatly appreciated! Regards - Jacob Sutton

As you noted in your comment, the while True: is your problem as it has no place in an event driven environment like turtle. Closing a window is an event that's firing asynchronous to your main loop. To make it synchronous, we can use an ontimer() event. I've made that change to your code below as well as thrown in other turtle idioms and code cleanup:

from turtle import Screen, Turtle

print("------------Space Invaders - Python------------")
print("-------------GAME NOT YET COMPLETED------------")
print("This console is simply a status readout.")

def move_left():
    new_x = player.xcor() - movementStepP

    if new_x < -380:
        new_x = -380

    player.setx(new_x)

def move_right():
    new_x = player.xcor() + movementStepP

    if new_x > 380:
        new_x = 380

    player.setx(new_x)

def move_enemy():
    global new_y, movementStepE

    new_x = enemy.xcor() + movementStepE

    if new_x > 380:
        movementStepE *= -1
        new_y += movementStepEY
        new_x = 380
    elif new_x < -380:
        movementStepE *= -1
        new_y += movementStepEY
        new_x = -380

    enemy.setposition(new_x, new_y)

    screen.ontimer(move_enemy, 50)

movementStepE = 2
movementStepEY = -15
movementStepP = 5

screen = Screen()
screen.bgcolor("black")
screen.title("Space Invaders")

borderPen = Turtle(visible=False)
borderPen.speed("fastest")
borderPen.color("white")
borderPen.pensize(3)

borderPen.penup()
borderPen.setposition(-400, -400)
borderPen.pendown()

for _ in range(4):
    borderPen.forward(800)
    borderPen.left(90)

player = Turtle("triangle")
player.speed("fastest")
player.setheading(90)
player.color("blue")
player.penup()
player.setposition(0, -350)

enemy = Turtle("circle")
enemy.speed("fastest")
enemy.color("red")
enemy.penup()
enemy.setposition(-300, 250)

screen.onkeypress(move_left, "Left")
screen.onkeypress(move_right, "Right")
screen.listen()

new_y = 250

move_enemy()

screen.mainloop()

print("-------PROGRAM TERMINATED INTENTIONALLY-------")

With this change, the console shows:

> python3 test.py
------------Space Invaders - Python------------
-------------GAME NOT YET COMPLETED------------
This console is simply a status readout.
-------PROGRAM TERMINATED INTENTIONALLY-------
>

Even when you close the window while the enemy is in motion.

You could also put a try catch statement round it as well, like so:

while True:
    try:
        x = enemy.xcor()
        y = enemy.ycor()
        new_x = x + movementStepE
        if new_x > 380:
            movementStepE = movementStepE * -1
            new_y = y + movementStepEY
            new_x = 380
        elif new_x < -380:
            movementStepE = movementStepE * -1
            new_y = y + movementStepEY
            new_x = -380
            enemy.setposition(new_x, new_y)
    except: #For more accuracy on catching, try something like 'except _tkinter.TclError:'
        break #if error raised

turtle.done()
print("-------PROGRAM TERMINATED INTENTIONALLY-------")

Please be aware though that without something like 'except _tkinter.TclError:' then any errors will just close the window.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM