I have been programming a python snake game using tkinter canvas and have been running into this error whilst trying to change the tickspeed for every apple eaten. Would be much appreciated if anyone could help as I am quite new to using tkinter and python in general.
File "c:\Users\Admin\Documents\pythonsnake.py", line 45, in main root.after(Tickspeed, main) UnboundLocalError: local variable 'Tickspeed' referenced before assignment
This is my code:
#Python Snake Game
from tkinter import Tk, Canvas
import random
import time
# Globals
WIDTH = 800
HEIGHT = 600
SEG_SIZE = 20
IN_GAME = True
Tickspeed = 100
# Helper functions
def create_block():
""" Creates an apple to be eaten """
global BLOCK
posx = SEG_SIZE * random.randint(1, (WIDTH-SEG_SIZE) / SEG_SIZE)
posy = SEG_SIZE * random.randint(1, (HEIGHT-SEG_SIZE) / SEG_SIZE)
BLOCK = c.create_oval(posx, posy,
posx+SEG_SIZE, posy+SEG_SIZE,
fill="red")
def main():
""" Handles game process """
global IN_GAME
if IN_GAME:
s.move()
head_coords = c.coords(s.segments[-1].instance)
x1, y1, x2, y2 = head_coords
# Check for collision with gamefield edges
if x2 > WIDTH or x1 < 0 or y1 < 0 or y2 > HEIGHT:
IN_GAME = False
# Eating apples
elif head_coords == c.coords(BLOCK):
s.add_segment()
c.delete(BLOCK)
if(Tickspeed>20):
Tickspeed = Tickspeed - 5
create_block()
# Self-eating
else:
for index in range(len(s.segments)-1):
if head_coords == c.coords(s.segments[index].instance):
IN_GAME = False
root.after(Tickspeed, main)
# Not IN_GAME -> stop game and print message
else:
set_state(restart_text, 'normal')
set_state(game_over_text, 'normal')
class Segment(object):
""" Single snake segment """
def __init__(self, x, y):
self.instance = c.create_rectangle(x, y,
x+SEG_SIZE, y+SEG_SIZE,
fill="white")
class Snake(object):
""" Simple Snake class convertable """
def __init__(self, segments):
self.segments = segments
# possible moves
self.mapping = {"Down": (0, 1), "Right": (1, 0),
"Up": (0, -1), "Left": (-1, 0)}
# initial movement direction
self.vector = self.mapping["Right"]
def move(self):
""" Moves the snake with the specified vector"""
for index in range(len(self.segments)-1):
segment = self.segments[index].instance
x1, y1, x2, y2 = c.coords(self.segments[index+1].instance)
c.coords(segment, x1, y1, x2, y2)
x1, y1, x2, y2 = c.coords(self.segments[-2].instance)
c.coords(self.segments[-1].instance,
x1+self.vector[0]*SEG_SIZE, y1+self.vector[1]*SEG_SIZE,
x2+self.vector[0]*SEG_SIZE, y2+self.vector[1]*SEG_SIZE)
def add_segment(self):
""" Adds segment to the snake """
last_seg = c.coords(self.segments[0].instance)
x = last_seg[2] - SEG_SIZE
y = last_seg[3] - SEG_SIZE
self.segments.insert(0, Segment(x, y))
def change_direction(self, event):
""" Changes direction of snake """
if event.keysym in self.mapping:
self.vector = self.mapping[event.keysym]
def reset_snake(self):
for segment in self.segments:
c.delete(segment.instance)
def set_state(item, state):
c.itemconfigure(item, state=state)
def clicked(event):
global IN_GAME
s.reset_snake()
IN_GAME = True
c.delete(BLOCK)
c.itemconfigure(restart_text, state='hidden')
c.itemconfigure(game_over_text, state='hidden')
start_game()
def start_game():
global s
create_block()
s = create_snake()
# Reaction on keypress
c.bind("<KeyPress>", s.change_direction)
main()
def create_snake():
# creating segments and snake
segments = [Segment(SEG_SIZE, SEG_SIZE),
Segment(SEG_SIZE*2, SEG_SIZE),
Segment(SEG_SIZE*3, SEG_SIZE)]
return Snake(segments)
# Setting up window cause fun yeah
root = Tk()
root.title("Python Snake Game By Amiel, Amitoj and Abdullah")
c = Canvas(root, width=WIDTH, height=HEIGHT, bg="#003344")
c.grid()
# catch keypressing
c.focus_set()
game_over_text = c.create_text(WIDTH/2, HEIGHT/2, text="GAME OVER!",
font='Calibi 30', fill='red',
state='hidden')
restart_text = c.create_text(WIDTH/2, HEIGHT-HEIGHT/3,
font='Arial 30',
fill='Black',
text=" Click here to restart" + '\n Made by Amiel & Amitoj & Abdullah',
state='hidden')
c.tag_bind(restart_text, "<Button-1>", clicked)
start_game()
root.mainloop()