简体   繁体   中英

Snake game in python Turtle.update() causes problems

So I was trying to create a game of snake using python but I seem to get this error message

Traceback (most recent call last):   
File "C:\Users\user\source\repos\PythonApplication1\PythonApplication1\PythonApplication1.py", line 85, in <module>
    wn.update()   
File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\turtle.py", line 1304, in update
    t._update_data()   
File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\turtle.py", line 2647, in _update_data
    self.screen._incrementudc()   
File "C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python39_64\lib\turtle.py", line 1293, in _incrementudc
    raise Terminator turtle.Terminator

I have tried some solutions I saw online but none of them worked

import turtle
import time
import random

delay = 0.1
score = 0

wn = turtle.Screen()
wn.title("Snake Game")
wn.bgcolor("blue")

wn.setup(width=600 ,height=600)
wn.tracer(0)

#HEAD
head = turtle.Turtle()
head.shape("square")
head.color("white")
head.penup()
head.goto(0,0)
head.direction = "stop"
#FOOD
food = turtle.Turtle()
colors = random.choice(['red','green','black'])
shapes = random.choice(['square','triangle','circle'])
food.speed(0)
food.shape(shapes)
food.color(colors)
food.penup()
food.goto(0,100)



pen = turtle.Turtle()
pen.speed(0)
pen.shape("square")
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0,250)
pen.write("Score : 0 High Score : 0",align="center",font=("candara",24,"bold"))


def goup():
    if head.direction !="down":
        head.direction = "up"

def godown():
    if head.direction !="up":
        head.direction ="down"

def goleft():
    if head.direction !="right":
        head.direction ="left"

def goright():
    if head.direction !="left":
        head.direction ="right"

def move():
    if head.direction == "up":
        y=head.ycor()
        head.sety(y+20)
    if head.direction == "down":
        y = head.ycor()
        head.sety(y-20)
    if head.direction == "left":
        x = head.xcor()
        head.setx(x-20)
    if head.direction == "right":
        x = head.xcor()
        head.setx(x+20)


wn.listen()
wn.onkeypress(goup,"w")
wn.onkeypress(godown,"s")
wn.onkeypress(goleft,"a")
wn.onkeypress(goright,"d")

segments = []

#Main Gameplay
while True:
    wn.update()
    if head.xcor()>290 or head.xcor()<-290 or head.ycor()>290 or head.ycor()<-290:
        time.sleep(1)
        head.goto(0,0)
        head.direction = "Stop"
        colors = random.choice(['red','blue','green'])
        shapes = random.choice(['square','circle'])
        for segment in segments:
            segments.goto(1000,1000)
        segments.clear()
        score = 0
        delay = 0.1
        pen.clear()
        pen.write("Score : 0 High Score : 0",align="center",font=("candara",24,"bold"))
    if head.distance(food)<20:
        x = random.randint(-270,270)
        y = random.randint(-270,270)

        #Adding segments
        new_segment = turtle.Turtle()
        new_segment.speed(0)
        new_segment.shape("square")
        new_segment.color("orange")
        new_segment.penup()
        segments.append(new_segment)
        delay -= 0.001
        score += 10
        if score > high_score:
            high_score = score
        pen.clear()
        pen.write("Score : {} High Score : {} ".format(score,high_score),align="center", font=("candara",24,"bold"))

        for index in range(len(segments)-1,0,-1):
            x = segments[index-1].xcor()
            y = segments[index-1].ycor()
            segments[index].goto(x,y)
        if len(segments) > 0:
            x = head.xcor()
            y = head.ycor()
            segments[0].goto(x,y)
        move()
        for segment in segments:
            if segment.distance(head) < 20:
                time.sleep(1)
                head.goto(0,0)
                head.direction = "Stop"
                colors = random.choice(['red','blue','green'])
                shapes = random.choice(['square','circle'])
                for segment in segments:
                    segment.goto(1000,1000)
                segment.clear()

                score = 0 
                delay = 0.1
                pen.clear()
                pen.write("Score : {} High Score : {} ".format(score,high_score),align="center", font=("candara",24,"bold"))
        time.sleep(delay)

wn.mainloop()

EDIT:

Original code has wrong indentations and some elements doesn't work.


I get this problem only when I close window with Turtle. And this is normal behaviour because when I close window then it still runs while -loop and wm.update() tries to access window which is already closed.

It would need to assign function which will be executed when window is closed and this function should stop while loop. But this need to use while running: with running = True and access root window created by tkinter and assign function (which will set running = False ) to even "WM_DELETE_WINDOW"

# ... code ...

running = True

def on_closing():
    global running
    
    running = False
    #root.destroy()
    
canvas = turtle.getcanvas()
root = canvas.winfo_toplevel()
root.protocol("WM_DELETE_WINDOW", on_closing)

while running:
   # ...code...

Full working code.

BTW: it doesn't need mainloop if you runs own loop with update()

import turtle
import time
import random

delay = 0.1
score = 0

wn = turtle.Screen()
wn.title("Snake Game")
wn.bgcolor("blue")

wn.setup(width=600 ,height=600)
wn.tracer(0)

#HEAD
head = turtle.Turtle()
head.shape("square")
head.color("white")
head.penup()
head.goto(0,0)
head.direction = "stop"
#FOOD
food = turtle.Turtle()
colors = random.choice(['red','green','black'])
shapes = random.choice(['square','triangle','circle'])
food.speed(0)
food.shape(shapes)
food.color(colors)
food.penup()
food.goto(0,100)



pen = turtle.Turtle()
pen.speed(0)
pen.shape("square")
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0,250)
pen.write("Score : 0 High Score : 0",align="center",font=("candara",24,"bold"))


def goup():
    if head.direction !="down":
        head.direction = "up"

def godown():
    if head.direction !="up":
        head.direction ="down"

def goleft():
    if head.direction !="right":
        head.direction ="left"

def goright():
    if head.direction !="left":
        head.direction ="right"

def move():
    if head.direction == "up":
        y=head.ycor()
        head.sety(y+20)
    if head.direction == "down":
        y = head.ycor()
        head.sety(y-20)
    if head.direction == "left":
        x = head.xcor()
        head.setx(x-20)
    if head.direction == "right":
        x = head.xcor()
        head.setx(x+20)


wn.listen()
wn.onkeypress(goup,"w")
wn.onkeypress(godown,"s")
wn.onkeypress(goleft,"a")
wn.onkeypress(goright,"d")

segments = []

running = True

def on_closing():
    global running
    
    running = False
    root.destroy()
    
canvas = turtle.getcanvas()
root = canvas.winfo_toplevel()
root.protocol("WM_DELETE_WINDOW", on_closing)

#Main Gameplay
while running:
    wn.update()
    if head.xcor()>290 or head.xcor()<-290 or head.ycor()>290 or head.ycor()<-290:
        time.sleep(1)
        head.goto(0,0)
        head.direction = "Stop"
        colors = random.choice(['red','blue','green'])
        shapes = random.choice(['square','circle'])
        for segment in segments:
            segments.goto(1000,1000)
        segments.clear()
        score = 0
        delay = 0.1
        pen.clear()
        pen.write("Score : 0 High Score : 0",align="center",font=("candara",24,"bold"))
    if head.distance(food)<20:
        x = random.randint(-270,270)
        y = random.randint(-270,270)

        #Adding segments
        new_segment = turtle.Turtle()
        new_segment.speed(0)
        new_segment.shape("square")
        new_segment.color("orange")
        new_segment.penup()
        segments.append(new_segment)
        delay -= 0.001
        score += 10
        if score > high_score:
            high_score = score
        pen.clear()
        pen.write("Score : {} High Score : {} ".format(score,high_score),align="center", font=("candara",24,"bold"))

    # --- after `if` ---

    for index in range(len(segments)-1,0,-1):
        x = segments[index-1].xcor()
        y = segments[index-1].ycor()
        segments[index].goto(x,y)
    if len(segments) > 0:
        x = head.xcor()
        y = head.ycor()
        segments[0].goto(x,y)
    move()
    for segment in segments:
        if segment.distance(head) < 20:
            time.sleep(1)
            head.goto(0,0)
            head.direction = "Stop"
            colors = random.choice(['red','blue','green'])
            shapes = random.choice(['square','circle'])
            for segment in segments:
                segment.goto(1000,1000)
            segment.clear()

            score = 0 
            delay = 0.1
            pen.clear()
            pen.write("Score : {} High Score : {} ".format(score,high_score),align="center", font=("candara",24,"bold"))
    time.sleep(delay)

#wn.mainloop()

OR you should use ontimer(func, time) instead of while -loop and time.sleep() - and then it should stop it when you close window

def gameloop():
    wn.update()
    # ... code without `while` and without `sleep`

    # run again 
    wn.ontimer(gameloop, 1000) # time in millisecons

# --- 

# run first time
wn.ontimer(gameloop, 1000) # time in millisecons

wn.mainloop()

BTW: but it needs to use global inside gameloop to assign values to global variables instead of local variables.


Full code

It needs mainloop() which will run gameloop() ever 1000 milliseconds.

import turtle
import time
import random

delay = 0.1
score = 0

wn = turtle.Screen()
wn.title("Snake Game")
wn.bgcolor("blue")

wn.setup(width=600 ,height=600)
wn.tracer(0)

#HEAD
head = turtle.Turtle()
head.shape("square")
head.color("white")
head.penup()
head.goto(0,0)
head.direction = "stop"
#FOOD
food = turtle.Turtle()
colors = random.choice(['red','green','black'])
shapes = random.choice(['square','triangle','circle'])
food.speed(0)
food.shape(shapes)
food.color(colors)
food.penup()
food.goto(0,100)



pen = turtle.Turtle()
pen.speed(0)
pen.shape("square")
pen.color("white")
pen.penup()
pen.hideturtle()
pen.goto(0,250)
pen.write("Score : 0 High Score : 0",align="center",font=("candara",24,"bold"))


def goup():
    if head.direction !="down":
        head.direction = "up"

def godown():
    if head.direction !="up":
        head.direction ="down"

def goleft():
    if head.direction !="right":
        head.direction ="left"

def goright():
    if head.direction !="left":
        head.direction ="right"

def move():
    if head.direction == "up":
        y=head.ycor()
        head.sety(y+20)
    if head.direction == "down":
        y = head.ycor()
        head.sety(y-20)
    if head.direction == "left":
        x = head.xcor()
        head.setx(x-20)
    if head.direction == "right":
        x = head.xcor()
        head.setx(x+20)


wn.listen()
wn.onkeypress(goup,"w")
wn.onkeypress(godown,"s")
wn.onkeypress(goleft,"a")
wn.onkeypress(goright,"d")

segments = []

high_score = 0

def gameloop():
    global score
    global delay
    global high_score
    # ... etc. ...

    wn.update()

    if head.xcor()>290 or head.xcor()<-290 or head.ycor()>290 or head.ycor()<-290:
        head.goto(0,0)
        head.direction = "Stop"
        colors = random.choice(['red','blue','green'])
        shapes = random.choice(['square','circle'])
        for segment in segments:
            segments.goto(1000,1000)
        segments.clear()
        score = 0
        delay = 0.1
        pen.clear()
        pen.write("Score : 0 High Score : 0",align="center",font=("candara",24,"bold"))
    if head.distance(food)<20:
        x = random.randint(-270,270)
        y = random.randint(-270,270)

        #Adding segments
        new_segment = turtle.Turtle()
        new_segment.speed(0)
        new_segment.shape("square")
        new_segment.color("orange")
        new_segment.penup()
        segments.append(new_segment)
        delay -= 0.001
        score += 10
        if score > high_score:
            high_score = score
        pen.clear()
        pen.write("Score : {} High Score : {} ".format(score,high_score),align="center", font=("candara",24,"bold"))

    # --- after `if` ---

    for index in range(len(segments)-1,0,-1):
        x = segments[index-1].xcor()
        y = segments[index-1].ycor()
        segments[index].goto(x,y)
    if len(segments) > 0:
        x = head.xcor()
        y = head.ycor()
        segments[0].goto(x,y)
    move()
    for segment in segments:
        if segment.distance(head) < 20:
            time.sleep(1)
            head.goto(0,0)
            head.direction = "Stop"
            colors = random.choice(['red','blue','green'])
            shapes = random.choice(['square','circle'])
            for segment in segments:
                segment.goto(1000,1000)
            segment.clear()

            score = 0 
            delay = 0.1
            pen.clear()
            pen.write("Score : {} High Score : {} ".format(score,high_score),align="center", font=("candara",24,"bold"))

    # run again 
    wn.ontimer(gameloop, 1000) # time in millisecons

# --- 

# run first time
wn.ontimer(gameloop, 1000) # time in millisecons

wn.mainloop()  # it needs `mainloop` 

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