Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.4 Tkinter-滞后_Python_Tkinter_Lag - Fatal编程技术网

Python 3.4 Tkinter-滞后

Python 3.4 Tkinter-滞后,python,tkinter,lag,Python,Tkinter,Lag,我正在为我在学校的python课做这个吃豆人项目游戏。一切都很顺利,但是。。。昨天,当我完成一些最后的功能时,我的游戏开始落后得很糟糕。我想问题在主循环中,但我找不到解决方案。。。下面是一些代码: from tkinter import * import time import threading from PIL import Image, ImageTk import random points = [] matrix = [] 班级游戏: def __init__(self):

我正在为我在学校的python课做这个吃豆人项目游戏。一切都很顺利,但是。。。昨天,当我完成一些最后的功能时,我的游戏开始落后得很糟糕。我想问题在主循环中,但我找不到解决方案。。。下面是一些代码:

from tkinter import *
import time
import threading
from PIL import Image, ImageTk
import random

points = []
matrix = []
班级游戏:

def __init__(self):
    self.tk = Tk()
    self.tk.title("Pac-man")
    self.canvas = Canvas(self.tk, width = 800, height = 700, bg = 'black')
    self.Pac = Pacman(self.canvas, 'yellow')
    self.Blinky = Ghost(self.canvas, 'red')
    self.score = 0
    self.scoreid = Label(self.tk,
                    text = "SCORE: {0}".format(self.score), bg = 'yellow', fg = 'black')
    self.scoreid.pack()
    for wall in outerWall: 
        self.drawWall(wall[0], wall[1], wall[2], wall[3])
        self.drawWall(800 - wall[0], wall[1], 800 - wall[2], wall[3])

    for wall in WierdWalls: 
        self.drawWall(wall[0], wall[1], wall[2], wall[3])
        self.drawWall(800 - wall[0], wall[1], 800 - wall[2], wall[3])

    for wall in BaseOfGhost:
        self.drawWall(wall[0], wall[1], wall[2], wall[3])
        self.drawWall(800 - wall[0], wall[1], 800 - wall[2], wall[3])
    self.canvas.create_line(350, 270, 450, 270, width = 5, fill = 'yellow')

    for wall in squareWalls: 
        self.drawSquareWall(wall[0], wall[1], wall[2], wall[3])
        self.drawSquareWall(800 - wall[0], wall[1], 800 - wall[2], wall[3])

    self.drawPoints()
    self.Pac.draw()
    self.canvas.pack()
    self.tk.update
    self.running = True

def drawWall(self, x0, y0, x1, y1, width = 3, color = 'blue'):
    self.canvas.create_line(x0, y0, x1, y1, width = width, fill = color)

def drawSquareWall(self, x0, y0, x1, y1, width = 2, color = 'black'):
    self.canvas.create_rectangle(x0, y0, x1, y1, fill = color)
    self.canvas.create_line(x0, y0, x1, y0, width = width, fill = 'blue')
    self.canvas.create_line(x1, y0, x1, y1, width = width, fill = 'blue')
    self.canvas.create_line(x1, y1, x0, y1, width = width, fill = 'blue')
    self.canvas.create_line(x0, y1, x0, y0, width = width, fill = 'blue')

def drawPoints(self):
    self.BuildHorizontalPath(40, 40, 13, 26)
    self.BuildVerticalPath(40, 40, 9, 16)
    self.BuildHorizontalPath(66, 168, 4, 26)
    self.BuildHorizontalPath(66, 104, 4, 26)
    self.BuildVerticalPath(170, 56, 8, 16)
    self.BuildVerticalPath(170, 192, 18, 24)
    self.BuildHorizontalPath(196, 104, 8, 26)
    self.BuildVerticalPath(352, 56, 3, 16)
    self.BuildHorizontalPath(40, 456, 5, 26)
    self.BuildHorizontalPath(40, 600, 5, 26)
    self.BuildVerticalPath(40, 472, 4, 16)
    self.BuildHorizontalPath(66, 520, 2, 26)
    self.BuildVerticalPath(92, 536, 4, 16 )
    self.BuildVerticalPath(40, 600, 4, 18)
    self.BuildHorizontalPath(66, 654, 12, 27)
    self.BuildHorizontalPath(200, 527, 7, 27)
    self.BuildHorizontalPath(200, 456, 7, 27)
    self.BuildVerticalPath (362, 472, 3, 18)
    self.BuildVerticalPath (274, 135, 3, 20)
    self.BuildHorizontalPath (292, 175, 4, 18)
    self.BuildVerticalPath (254, 550, 3, 20)
    self.BuildHorizontalPath (274, 591, 5, 22)
    self.BuildVerticalPath (363, 611, 2, 20)

def BuildHorizontalPath(self, val1, val2, number, increment = 25, delta = 8):
    x, y = val1, val2
    itemid1 = 0
    itemid2 = 0
    for i in range(number):
        deltax = x + delta
        deltay = y + delta
        itemid1 = self.canvas.create_oval(x, y, deltax, deltay, fill = 'white')
        itemid2 = self.canvas.create_oval(800-x, y, 800-deltax, deltay, fill = 'white')
        points.append([(deltax + x)/2, (deltay + y)/2, itemid1])
        points.append([800-(deltax + x)/2, (deltay+y)/2, itemid2])
        x += increment

def BuildVerticalPath(self, val1, val2, number, increment = 30, delta = 8):
    itemid1 = 0
    itemid2 = 0
    for i in range(number):
        x, y = val1, val2
        deltax = x + delta
        deltay = y + delta
        itemid1 = self.canvas.create_oval(x, y, deltax, deltay, fill = 'white')
        itemid2 = self.canvas.create_oval(800-x, y, 800-deltax, deltay, 
            fill = 'white')
        points.append([(deltax + x)/2, (deltay + y)/2, itemid1])
        points.append([800-(deltax + x)/2, (deltay + y)/2, itemid2])
        val2 += increment

def mainloop(self):
    while 1:
        if self.running:
            first_moment = round(time.time())
            if not self.Pac.hitwall():
                self.Pac.canvas.move(self.Pac.id, self.Pac.x, self.Pac.y)
            if self.Pac.feed():
                self.score = self.score + 10
                self.scoreid.config(text = "SCORE: {0}".format(self.score))
            if self.Pac.first_teleport():
                self.Pac.canvas.move(self.Pac.id, 760, 0)

            if self.Pac.second_teleport():
                self.Pac.canvas.move(self.Pac.id, -760, 0)

            if not self.Blinky.hitwall():
                self.Blinky.canvas.move(self.Blinky.id, self.Blinky.x, self.Blinky.y)
            if self.Blinky.hitwall():
                self.Blinky.change_direction()

            last_moment = round(time.time())
            self.tk.update_idletasks()
            self.tk.update()
            s = 0.01 - (last_moment - first_moment)
            if s >= 0:
                time.sleep(s)
吃豆人:

def __init__(self, canvas, color):
    self.canvas = canvas
    self.id = canvas.create_oval(10, 10, 35, 35, fill = color)
    self.canvas.move(self.id, 400, 375)
    self.x = 0
    self.y = 0
    self.canvas.bind_all('<KeyPress-Left>', self.turn_left)
    self.canvas.bind_all('<KeyPress-Right>', self.turn_right)
    self.canvas.bind_all('<KeyPress-Up>', self.go_up)
    self.canvas.bind_all('<KeyPress-Down>', self.go_down)
    self.canvas.bind_all('<KeyRelease>', self.stop)
    #self.canvas.bind_all(self.hitwall, self.stop)

def feed(self):
    pos = self.canvas.coords(self.id)
    for point in points:
        if  point[0] >= pos[0] and point[0] <= pos[2]:
            if point[1] >= pos[1] and point[1] <= pos[3]:
                self.canvas.delete(point[2])
                points.remove(point)
                return True
        if  point[1] >= pos[1] and point[1] <= pos[3]:
            if point[0] >= pos[0] and point[0] <= pos[2]:
                self.canvas.delete(point[2])
                points.remove(point)
                return True
    return False

def stop(self, event):
    self.x = 0
    self.y = 0

def turn_left(self, event):
    self.x = -2

def turn_right(self, event):
    self.x = 2

def go_up(self, event):
    self.y = -2

def go_down(self, event):
    self.y = 2

def draw(self):
    self.canvas.move(self.id, self.x, self.y)

def hitwall(self):
    pos = self.canvas.coords(self.id)
    pos[0] += self.x
    pos[1] += self.y
    pos[2] += self.x
    pos[3] += self.y
    for wall in squareWalls:
        if pos[1] in range(wall[1], wall[3]):
            if pos[0] in range(wall[0], wall[2]):
                return True
            if pos[2] in range(wall[0], wall[2]):
                return True
        elif pos[3] in range(wall[1], wall[3]):
            if pos[0] in range(wall[0], wall[2]):
                return True
            if pos[2] in range(wall[0], wall[2]):
                return True
        if pos[1] in range(wall[1], wall[3]):
            if pos[0] >= 800 - wall[2] and pos[0]<= 800 - wall[0]:
                return True
            if pos[2] >= 800 - wall[2] and pos[2]<= 800 - wall[0]:
                return True
        elif pos[3] in range(wall[1], wall[3]):
            if pos[0] >= 800 - wall[2] and pos[0]<= 800 - wall[0]:
                return True
            if pos[2] >= 800 - wall[2] and pos[2]<= 800 - wall[0]:
                return True

    for wall in outerWall:
        if pos[1] > 90 and pos[3] < 680:

            if pos[0] <= wall[0] and pos[0] <= wall[2]:
                if pos[1] in range(wall[1], wall[3]):
                    return True

            if pos[2] <= wall[0] and pos[2] <=wall[2]:
                if pos[3] in range(wall[1], wall[3]):
                    return True

        if pos[3] > 680 or pos[1] < 20:
            return True

        if pos[1] > 20 and pos[1] < 90:
            if pos[0] < 20:
                return True
            if pos[2] > 780:
                return True
            if pos[2] > 385 and pos[2] < 415:
                return True
            if pos[0] > 385 and pos[0] < 415:
                return True

        if pos[1] > 90 and pos[3] < 680:

            if pos[0] >= 800 - wall[0] and pos[0] >= 800 - wall[2]:
                if pos[1] in range(wall[1], wall[3]):
                    return True

            if pos[2] >= 800 - wall[0] and pos[2] >= 800 - wall[2]:
                if pos[3] in range(wall[1], wall[3]):
                    return True

    for wall in list_of_walls:
        if pos[1] in range(wall[1], wall[3]):
            if pos[0] in range(wall[0], wall[2]):
                return True
            if pos[2] in range(wall[0], wall[2]):
                return True
        elif pos[3] in range(wall[1], wall[3]):
            if pos[0] in range(wall[0], wall[2]):
                return True
            if pos[2] in range(wall[0], wall[2]):
                return True
        if pos[1] in range(wall[1], wall[3]):
            if pos[0] >= 800 - wall[2] and pos[0]<= 800 - wall[0]:
                return True
            if pos[2] >= 800 - wall[2] and pos[2]<= 800 - wall[0]:
                return True
        elif pos[3] in range(wall[1], wall[3]):
            if pos[0] >= 800 - wall[2] and pos[0]<= 800 - wall[0]:
                return True
            if pos[2] >= 800 - wall[2] and pos[2]<= 800 - wall[0]:
                return True

    return False 

def first_teleport(self):
    pos = self.canvas.coords(self.id)
    if pos[1] > 290 and pos[1] < 350:
        if pos[0] < 0:
            return True
    return False

def second_teleport(self):
    pos = self.canvas.coords(self.id)
    if pos[3] > 290 and pos[3] < 350:
        if pos[2] > 800:
            return True
    return False
班鬼(吃豆人):

def\uuuuu init\uuuuuuuuu(自我、画布、颜色):
self.canvas=画布
self.id=canvas.create_oval(10,10,35,35,fill=color)
self.canvas.move(self.id,350220)
self.x=-2
self.y=0
def移动(自):
如果self.x>0:
自行右转
如果self.x<0:
自行左转
如果self.y>0:
自我毁灭
如果self.y<0:
自我提升
def更改方向(自身):
z=随机随机。随机范围(1,4)
如果z==1:
self.x=0
self.y=2
elif z==2:
self.x=2
self.y=0
elif z==3:
self.x=0
self.y=-2
elif z==4:
self.x=-2
self.y=0
外墙=[[5,5,5200],[5,5400,5],[20,20,20200],
[20, 20, 385, 20], [5, 200, 5, 215], [20, 200, 150, 200], [5, 215, 135, 215], [135, 215, 135, 275],[150, 200, 150, 290], [135, 215, 135, 275], [5, 290, 150, 290], [5, 275, 135, 275], [5, 350, 150, 350], [5, 365, 135, 365],
[150, 350, 150, 440] , [135, 365, 135, 425], [20, 440, 150, 440], [5, 425, 135, 425], [5, 425, 5, 695], [20, 440, 20, 545], [20, 575, 20, 680], [20, 545, 60, 545], [20, 575, 60, 575], [60, 545, 60, 575], [5, 695, 795, 695], [385, 20, 385, 90], [385, 90, 400, 90], [20, 680, 780, 680]]
方墙=[[60,60,150,90],[200,60,340,90],[60,130,150,150],[200,350,240,440],[200,490,340,510]]
BaseOfGhost=[[300270300370]、[310280310360]、[300270350270]、[300370400370]、[310360400360]、[310280350280]、[350280270]]
wierdwarls=[[300,140,500,140],[500,140,500,160],[500,160,410,160],[300,140,300,160],[300,160,390,160],[390,160,390,220],[410,160,410,220],[390,220,410,220],[560,140,560,200],[560,200,480,200],[480,200,480,480,220],[480,220,560],[560,290],[560,600],[560, 140, 600, 140], [150, 480, 150, 575], [150, 480, 60, 480], [60, 480, 60, 500], [60, 500, 130, 500], [130, 500, 130, 575], [130, 575, 150, 575], [300, 440, 390, 440 ], [300, 440, 300, 420], [300, 420, 500, 420], [390, 440, 390, 510], [390, 510, 410, 510],[300, 580, 390, 580 ], [300, 580, 300, 550], [300, 550, 500, 550], [390, 580, 390, 640], [390, 640, 410, 640], [60, 640, 340, 640], [60, 640, 60, 620], [60, 620, 200, 620], [200, 620, 200, 550], [200, 550, 220, 550,],[220, 550, 220, 620], [220, 620, 340, 620], [340, 620, 340, 640] ] 
墙壁清单=[300140500160]、[390160410220]、[560140600290]、[560200480220]、[240200320220]、[240140200290]、[150480130575]、[150480,60500]、[650480740500]、[65048070500]、[300420500440]、[390440410510]、[300550500580]、[390580410640]、[60620340640]、[4606207074040]、[200550220620],[580,550,600, 620], [300, 270, 400, 370]]
m=菜单()
m、 mainloop()
我关心的是,这个函数是否太大,因为到目前为止,我在这个主循环中使用了两次,我还需要两次以上。。。
如果有人能帮我找到这个问题的解决方案,我会非常高兴,因为这个项目对我来说非常重要。

在游戏初始化时,你们可以做一些预处理,并在逻辑上将游戏场划分为四个象限,然后为每个象限建立一个列表,其中只包括完全或部分位于注册表中的墙离子


对于这样的列表,您可以通过只查看与
Pacman
当前所在区域相对应的墙(并忽略其他区域列表中的墙)来加速
hitwall()
。这将大大减少所需的比较次数-如果墙是随机分布的,并且
Pacman
完全位于其中一个象限内,则最多可减少75%。

调用
sleep
会导致程序延迟。可能还有其他问题,但这肯定是其中之一。你不应该这样做如果使用自己的
mainloop
方法,则应使用内置的
mainloop
功能

您可以通过从
mainloop
中删除while语句、删除sleep语句以及对
update
update\u idletasks
的调用,然后让它使用
after
命令使自己每隔几毫秒运行一次

它看起来像这样:

def animate(self):

    <all of the code for updating the display>

    self.after(30, self.animate)
您可以在一些地方使用
else
来减少计算量。例如,如果
hitwall()
返回
True
,则可能不需要同时调用
feed()
,对吗?而且,如果吃豆人击中第一个传送站,就不需要检查它是否在第二个传送站。正确使用
else
可以减少三分之一或更多的计算量


另外,您正在调用self.Blinky.hitwall()每次迭代两次。你不应该只调用一次吗?

一个小的代码优化是使用
if low
而不是
if value>low和value
进行范围检查。你需要修复问题的标记。有些代码没有标记为代码,这使得你的代码无法进行合作正确地复制和粘贴。你的答案真的很有帮助!!!非常感谢!我不知道这个方法。可能是因为这是我的第一个2D游戏项目…感谢你,希望我能完成它:)@SpmiR:我相信你会在
菜单中调用它。play()
使用
g.animate()
而不是
g.mainloop()
您现在有了。
def __init__(self, canvas, color):
    self.canvas = canvas
    self.id = canvas.create_oval(10, 10, 35, 35, fill = color)
    self.canvas.move(self.id, 350, 220)
    self.x = -2
    self.y = 0

def movement(self):
    if self.x > 0:
        self.turn_right
    if self.x < 0:
        self.turn_left
    if self.y > 0:
        self.go_down
    if self.y < 0:
        self.go_up

def change_direction(self):
    z = random.randrange(1, 4)
    if z == 1:
        self.x = 0
        self.y = 2
    elif z == 2:
        self.x = 2
        self.y = 0
    elif z == 3:
        self.x = 0
        self.y = -2
    elif z == 4:
        self.x = -2
        self.y = 0



outerWall = [ [5, 5, 5, 200], [5, 5, 400, 5], [20, 20, 20, 200],
[20, 20, 385, 20], [5, 200, 5, 215], [20, 200, 150, 200], [5, 215, 135, 215], [135, 215, 135, 275],[150, 200, 150, 290], [135, 215, 135, 275], [5, 290, 150, 290], [5, 275, 135, 275], [5, 350, 150, 350], [5, 365, 135, 365],
[150, 350, 150, 440] , [135, 365, 135, 425], [20, 440, 150, 440], [5, 425, 135, 425], [5, 425, 5, 695], [20, 440, 20, 545], [20, 575, 20, 680], [20, 545, 60, 545], [20, 575, 60, 575], [60, 545, 60, 575], [5, 695, 795, 695], [385, 20, 385, 90], [385, 90, 400, 90], [20, 680, 780, 680]]

squareWalls = [[60, 60, 150, 90], [200, 60, 340, 90], [60, 130, 150, 150], [200, 350, 240, 440], [200, 490, 340, 510]]

BaseOfGhost = [[300, 270, 300, 370], [310, 280, 310, 360], [300, 270, 350, 270], [300, 370, 400, 370], [310, 360, 400, 360], [310, 280, 350, 280],[350, 280, 350, 270] ]

WierdWalls = [[300, 140, 500, 140], [500, 140, 500, 160], [500, 160, 410, 160],[300, 140, 300, 160], [300, 160, 390, 160], [390, 160, 390, 220], [410, 160, 410, 220], [390, 220, 410 , 220], [560, 140, 560, 200], [600, 140, 600, 290], [560, 200, 480, 200], [480, 200, 480, 220], [480, 220, 560, 220], [560, 220, 560, 290], [560, 290, 600, 290], [560, 140, 600, 140], [150, 480, 150, 575], [150, 480, 60, 480], [60, 480, 60, 500], [60, 500, 130, 500], [130, 500, 130, 575], [130, 575, 150, 575], [300, 440, 390, 440 ], [300, 440, 300, 420], [300, 420, 500, 420], [390, 440, 390, 510], [390, 510, 410, 510],[300, 580, 390, 580 ], [300, 580, 300, 550], [300, 550, 500, 550], [390, 580, 390, 640], [390, 640, 410, 640], [60, 640, 340, 640], [60, 640, 60, 620], [60, 620, 200, 620], [200, 620, 200, 550], [200, 550, 220, 550,],[220, 550, 220, 620], [220, 620, 340, 620], [340, 620, 340, 640] ] 

list_of_walls = [[300,140,500,160],[390,160,410,220], [560,140,600,290],[560,200,480,220], [240,200,320,220],[240,140,200,290],[150,480,130,575], [650,480,670,575], [150,480,60,500], [650,480,740,500], [300,420,500,440], [390,440,410,510], [300,550,500,580], [390,580,410,640], [60,620,340,640], [460,620,740,640], [200,550,220,620], [580,550,600, 620], [300, 270, 400, 370]]

m = Menu()
m.mainloop()
def animate(self):

    <all of the code for updating the display>

    self.after(30, self.animate)
def animate(self):
    if self.running:
        if not self.Pac.hitwall():
            self.Pac.canvas.move(self.Pac.id, self.Pac.x, self.Pac.y)
        if self.Pac.feed():
            self.score = self.score + 10
            self.scoreid.config(text = "SCORE: {0}".format(self.score))
        if self.Pac.first_teleport():
            self.Pac.canvas.move(self.Pac.id, 760, 0)

        if self.Pac.second_teleport():
            self.Pac.canvas.move(self.Pac.id, -760, 0)

        if not self.Blinky.hitwall():
            self.Blinky.canvas.move(self.Blinky.id, self.Blinky.x, self.Blinky.y)
        if self.Blinky.hitwall():
            self.Blinky.change_direction()

        self.after(30, self.animate)