Битва-Игра змея в tkinter


Отказ от ответственности: этот код еще далек от завершения, я в курсе вопросов, касающихся моих стандартов именования, мое отсутствие замечаний и читабельность, однако я столкнулся с большой проблемой, которая мешает мне редактирование, тестирование и завершение игры. Это не функциональные проблемы, но и проблемы с производительностью. Если вы хотите более подробное объяснение, это то, что я ранее писал на переполнение стека;

Я строю следующую игру в tkinter, по сути это змея игры с двумя игроками. Где вы будет сражаться с другим игроком, пока один из вас ударит другого, стене или заканчивается свободное место. Для создания "игры" я использую полотна, которые создаются в сетке. Я думаю, что это может быть причиной следующей проблемы: при попытке закрыть программа, питон и скрипт будет полностью заморозить и займет примерно 5-10 секунд, чтобы закрыть. Я знаю, что tkinter не может быть лучшим вариантом для создания игр, однако это путь, который я выбрал и хотел бы знать, если есть какой-то способ исправить мою проблему.

Резюмируем: при попытке закрыть программу - окне застывает в течение приблизительно 5-10 секунд. Затем он закрывает, но, очевидно, тестирование и сам геймплей мешает.

Одно замечание я хотел бы сделать является то, что игра загружается намного быстрее чем она закрывается, которые я нахожу странными. Каких-либо оптимизаций, которые вы можно рекомендовать также будет приветствовать я понимаю, что Обмен стека больше платформой для этого.

from tkinter import *
from random import randint
import os

velocity = [1,0]
velocity2 = [-1,0]
grid = []
coord = [[10,10]]
coord2 = [[20,20]]
time = 0 
end = False
colour1 = "#d35400"
colour2 = "#9b59b6"
winner = 0
size1 = 0
size2 = 0
loopIds = []
speed1 = 50
speed2 = 50
powers = ["#2ecc71","#e74c3c","#ecf0f1"]
up1 = 0
up2 = 0
down1 = 0
down2 = 0
points1 = 0
points2 = 0

master = Tk()
master.config(bg="#222")
master.title("Trail Snake")
master.wm_state('zoomed')
master.resizable(0, 0)

def start():
    global coord, coord2, colour1, colour2
    for i in coord:
        grid[i[0]][i[1]].config(bg=colour1)
    for i in coord2:
        grid[i[0]][i[1]].config(bg=colour2)

def genPower():
    global h, w, powers
    power = randint(0,2)
    location = [randint(0,h-1), randint(0,h-1)]
    while grid[location[0]][location[1]].cget("bg") != "#222":
        location = [randint(0,h-1), randint(0,h-1)]
    grid[location[0]][location[1]].config(bg=powers[power])

def clear():
    for n in grid:
        for i in n:
            i.config(bg="#222")

def move():
    global coord, coord2, colour1, colour2, size1, size2
    moveSnake(coord, colour1, size1)
    moveSnake(coord2, colour2, size2)

def moveSnake(snake, colour, size):
    global end, h, w, colour1, winner, velocity, velocity2, loopIds, speed1, speed2, powers, up1, up2, down1, down2
    if colour == colour1:
        movement = velocity
        speed = speed1
    else:
        movement = velocity2
        speed = speed2
    if up1 == 0 and down2 == 0:
        speed1 = 50
    if up2 == 0 and down1 == 0:
        speed2 = 50
    if not(snake[0][0]+movement[0] >= 0 and snake[0][0]+movement[0] <= (h-1) and snake[0][1]+movement[1] >= 0 and snake[0][1]+movement[1] <= (w-1)):
        end = True
        if colour == colour1:
            winner = "Purple"
        else:
            winner = "Orange"
    if not end:
        for i in snake:
            grid[i[0]][i[1]].config(bg="#222")
        snake.insert(0, [snake[0][0] + movement[0], snake[0][1] + movement[1]])
        if size == 0:
            chance = randint(1,20)
            if chance == 1:
                size = randint(1,3)
        if size != 0:
            snake.pop()
            path = snake[0]
            size -= 1
        else:
            path = snake.pop()
        for i in snake:
            if grid[i[0]][i[1]].cget("bg") == "#222":
                grid[i[0]][i[1]].config(bg=colour)
            elif grid[i[0]][i[1]].cget("bg") in powers:
                power = powers.index(grid[i[0]][i[1]].cget("bg"))
                if power == 0:
                    if colour == colour1:
                        if up1 == 0:
                            speed1 = 1
                            up1 += 5
                    else:
                        if up2 == 0:
                            speed2 = 1
                            up2 += 5
                elif power == 1:
                    if colour == colour1:
                        if down1 == 0:
                            speed2 = 200
                            down1 += 10
                    else:
                        if down2 == 0:
                            speed1 = 200
                            down2 += 10
                else:
                    clear()
            else:
                end = True
                if colour == colour1:
                    winner = "Purple"
                else:
                    winner = "Orange"
        grid[path[0]][path[1]].config(bg=colour)
        chance = randint(1,100)
        if chance == 1:
            genPower()
        loopId = master.after(speed, lambda snake=snake, colour=colour, size=size: moveSnake(snake, colour, size))
        loopIds.append(loopId)
    else:
        pass # WINNER  

def changeDir(changeDir):
    global velocity
    if velocity[0] == changeDir[1] or velocity[1] == changeDir[0]:
        velocity = changeDir

def changeDir2(changeDir):
    global velocity2
    if velocity2[0] == changeDir[1] or velocity2[1] == changeDir[0]:
        velocity2 = changeDir

def displayGame():
    global h, w
    try:
        main.destroy()

    except: pass

    global wrapper, scoreCount, totalScore, bottom, game

    wrapper = Frame(master, bg="#3498db")
    wrapper.pack(fill=X)

    gameTitle = Label(wrapper ,text="Trail Snake", bg="#3498db", fg="#fff", height=1, pady=10, font=('century gothic',(18)))
    gameTitle.pack(side="top")

    gameWrapper = Frame(bg="#222")
    gameWrapper.pack(expand=True, fill=X, padx=200)

    game = Frame(gameWrapper, bg="#eee", highlightbackground="#2980b9", highlightthickness=5)
    game.pack(side="right")
    game.propagate(0)

    scoresMessage = Label(gameWrapper, anchor="w", fg="#fff", text="Scores this round: (5 games played)", font=('century gothic',(20)), bg="#222")
    scoresMessage.pack(anchor="w")

    playerOneScore = Frame(gameWrapper, padx=10, pady=10, bg="#9b59b6")
    playerOneScore.pack(anchor="w")

    playerScoreIncrease = Label(playerOneScore, text="+1", bg="#8e44ad")
    playerScoreIncrease.pack(side="left")

    WINDOW_WIDTH = master.winfo_screenwidth() / 3
    WINDOW_HEIGHT = master.winfo_screenheight() / 2

    game.config(width=WINDOW_WIDTH, height=WINDOW_HEIGHT)

    SW = game.winfo_screenwidth()
    SH = game.winfo_screenheight()

    h = round(((SH-10) / 15)) - 10
    w = round(((SW-10) / 15))
    w = round(w / 1.8)

    for n in range(0, h):
        grid.append([])
        for i in range(0,w):
            grid[n].append(Canvas(game, bg="#222", height="15", width="15", highlightthickness="0"))
            grid[n][i].grid(row=n, column=i)

    start()
    move()

def restart(event=None):
    global coord, coord2, grid, velocity, velocity2, score, end, loopIds, time, timerId, speed1, speed2, up1, up2, down1, down2

    for n in grid:
        for i in n:
            i.config(bg="#222")
    for i in loopIds:
        master.after_cancel(i)
    loopIds = []
    velocity = [1,0]
    velocity2 = [-1,0]
    coord = [[10,10]]
    coord2 = [[40,50]]
    score = 0 
    end = False
    time = 0
    speed1 = 50
    speed2 = 50
    up1 = 0
    up2 = 0
    down1 = 0
    down2 = 0

    master.after_cancel(timerId)

    start()
    move()

def mainMenu():

    global main

    main = Frame(master, pady=20, padx=20, bg="#333")
    main.pack(expand=True, padx=20, pady=20)

    mainLbl = Label(main ,text="Click Start To Begin!", bg="#3498db",anchor="n", fg="#fff", height=1, width=40, pady=20, font=('century gothic',(18)))
    mainLbl.pack(pady=(0,0), fill=X)

    startGame = Button(main, text="Start", command=displayGame, bg="#2ecc71", borderwidth=0, relief=FLAT, height=2, fg="#fff", font=('century gothic',(14)))
    startGame.pack(pady=(10,0), fill=X)

mainMenu()

master.bind("<Up>", lambda Event=None: changeDir2([-1,0]))
master.bind("<Down>", lambda Event=None: changeDir2([1,0]))
master.bind("<Left>", lambda Event=None: changeDir2([0,-1]))
master.bind("<Right>", lambda Event=None: changeDir2([0,1]))

master.bind("<w>", lambda Event=None: changeDir([-1,0]))
master.bind("<s>", lambda Event=None: changeDir([1,0]))
master.bind("<a>", lambda Event=None: changeDir([0,-1]))
master.bind("<d>", lambda Event=None: changeDir([0,1]))
master.bind("<F5>", restart)

master.bind("<F6>", lambda x: master.destroy())
master.mainloop()


Комментарии