Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/352.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上的这个小游戏(155行长)运行得这么慢?_Python_Optimization_Pygame - Fatal编程技术网

为什么Python上的这个小游戏(155行长)运行得这么慢?

为什么Python上的这个小游戏(155行长)运行得这么慢?,python,optimization,pygame,Python,Optimization,Pygame,我已经从主回路中切下了我能切下的所有东西。我还优化了动态和静态对象的碰撞,大大减少了迭代次数。但在他的机器上仍然很慢。我将针对有人想要测试它的情况发布整个文件,但是您可以直接跳转到主循环的“whileexit==false:” 导入pygame 从pyeuclid导入向量2 从数学输入sin,cos,pi 从随机导入随机 课程内容: 定义初始(自我,位置): self.pos=pos 事物。附加(自我) def更新(自我):通过 def牵引(自身,img):通过 def碰撞(自我,谁):通过 类

我已经从主回路中切下了我能切下的所有东西。我还优化了动态和静态对象的碰撞,大大减少了迭代次数。但在他的机器上仍然很慢。我将针对有人想要测试它的情况发布整个文件,但是您可以直接跳转到主循环的“whileexit==false:”

导入pygame
从pyeuclid导入向量2
从数学输入sin,cos,pi
从随机导入随机
课程内容:
定义初始(自我,位置):
self.pos=pos
事物。附加(自我)
def更新(自我):通过
def牵引(自身,img):通过
def碰撞(自我,谁):通过
类动态(事物):
定义初始(自我,位置):
事物。初始(自我,位置)
self.vel=Vector2(0,0)
self.lastPos=pos
self.col=(255255,0)
自相关系数r=12
动态_things.append(self)
def更新(自我):
self.lastPos=self.pos
self.pos=self.pos+self.vel
def牵引(自身、img):
pygame.draw.circle(img,(0,0,0),[int(n)表示self.pos中的n],self.r,self.r)
pygame.draw.circle(img,self.col,[int(n)表示self.pos中的n],self.r-2,self.r-2)
def碰撞(自身、obj):
物体碰撞(自我,物体)
如果存在(obj,墙壁):
self.pos=self.lastPos
班墙(东西):
def牵引(自身、img):
x、 y=自身位置x,自身位置y
pygame.draw.rect(img,(90,90200),(x-16,y-16,32,32),0)
Pacman级(动态):
定义初始化(自):
动态初始化(self,Vector2(32*9+16,32*12+16))
self.col=(255255,0)
def更新(自我):
动态更新(自我)
如果(按下[pygame.K_LEFT]):self.vel.x=-1
如果(按下[pygame.K_RIGHT]):self.vel.x=1
如果(按下[pygame.K_DOWN]):self.vel.y=1
if(按[pygame.K_UP]键):self.vel.y=-1
如果(self.vel.x==-1且未按下[pygame.K_LEFT]):self.vel.x=0
如果(self.vel.x==1且未按下[pygame.K_RIGHT]):self.vel.x=0
如果(self.vel.y==1且未按下[pygame.K_DOWN]):self.vel.y=0
如果(self.vel.y==-1且未按下[pygame.K_UP]):self.vel.y=0
def碰撞(自身、obj):
动态碰撞(self,obj)
如果存在(对象、重影):
self.pos=Vector2(32*9+16,32*12+16)
类重影(动态):
定义初始化(自):
动态初始化(self,Vector2(32*9+16,32*10+16))
self.col=(int(random()*255)、int(random()*255)、int(random()*255))
self.vel=Vector2(0,-2)
def更新(自我):
动态更新(自我)

if random()可能不是速度慢的主要原因,但是“while exit==False:”需要比“while not exit:”多一点字节码才能执行。

您在每个循环中都会重新绘制和翻转整个屏幕。我没有测试你的程序,但是在我知道的pacman上,屏幕上只有5个移动的精灵,你应该试着每帧只对它们进行blit(当然,如果其他东西发生了变化,也应该如此)。并且不显示.flip(),只需更新您更改的屏幕区域(通常会加快很多)


当然,你需要停止在每一个画面上空白,并且会有很多关于更新内容的管理。在pygame中有一些对脏精灵的额外支持,可以帮助您实现这一点。或者,你可以只更新所有“活动”精灵,将它们所在的位置置空,并在新位置重新绘制它们(显然,这两个区域中的所有内容)。在列表中收集受影响的矩形,并将其传递给update_rects(),而不是翻转屏幕。在pacman游戏中,应该没有必要在每一帧中都画墙…

您是否尝试分析代码以查看瓶颈发生的位置?您画的太多了。与问题无关,我只是在代码中注意到了一些其他事情:在“#更多鬼”下你不应该在游戏中使用无限的随机性。定义一个随机间隔(如10-30秒)代替每个幽灵产卵。列文,如何?伊格纳西奥,你能详细说明一下并提出一个替代方案吗?当然,谢谢。看看这些链接就可以开始了:和。通过这种方式,您可以将精力集中在将产生最大潜在加速的代码上。
import pygame
from pyeuclid import Vector2
from math import sin,cos,pi
from random import random

class Thing:
    def __init__(self,pos):
        self.pos = pos
        things.append(self)
    def update(self): pass
    def draw(self,img): pass
    def collide(self,who): pass

class DynamicThing(Thing):
    def __init__(self,pos):
        Thing.__init__(self,pos)
        self.vel = Vector2(0,0)
        self.lastPos = pos
        self.col = (255,255,0)
        self.r = 12
        dynamic_things.append(self)
    def update(self):
        self.lastPos = self.pos
        self.pos = self.pos + self.vel
    def draw(self,img):
        pygame.draw.circle(img, (0,0,0), [int(n) for n in self.pos], self.r, self.r)
        pygame.draw.circle(img, self.col, [int(n) for n in self.pos], self.r-2, self.r-2)
    def collide(self,obj):
        Thing.collide(self,obj)
        if isinstance(obj,Wall): 
            self.pos = self.lastPos

class Wall(Thing):
    def draw(self,img):
        x,y = self.pos.x, self.pos.y
        pygame.draw.rect(img, (90,90,200), (x-16,y-16,32,32), 0)

class Pacman(DynamicThing):
    def __init__(self):
        DynamicThing.__init__(self,Vector2(32*9+16,32*12+16))
        self.col = (255,255,0)
    def update(self):
        DynamicThing.update(self)
        if (keyPressed[pygame.K_LEFT]): self.vel.x = -1
        if (keyPressed[pygame.K_RIGHT]): self.vel.x = 1
        if (keyPressed[pygame.K_DOWN]): self.vel.y = 1
        if (keyPressed[pygame.K_UP]): self.vel.y = -1
        if (self.vel.x==-1 and not keyPressed[pygame.K_LEFT]): self.vel.x = 0
        if (self.vel.x==1 and not keyPressed[pygame.K_RIGHT]): self.vel.x = 0
        if (self.vel.y==1 and not keyPressed[pygame.K_DOWN]): self.vel.y = 0
        if (self.vel.y==-1 and not keyPressed[pygame.K_UP]): self.vel.y = 0
    def collide(self,obj):
        DynamicThing.collide(self,obj)
        if isinstance(obj,Ghost):
            self.pos = Vector2(32*9+16,32*12+16)

class Ghost(DynamicThing):
    def __init__(self):
        DynamicThing.__init__(self,Vector2(32*9+16,32*10+16))
        self.col = (int(random()*255),int(random()*255),int(random()*255))
        self.vel = Vector2(0,-2)
    def update(self):
        DynamicThing.update(self)
        if random()<0.01:
            self.vel = [Vector2(2,0),Vector2(-2,0),Vector2(0,2),Vector2(0,-2)][int(random()*4)]
    def collide(self,obj):
        DynamicThing.collide(self,obj)
        if isinstance(obj,Wall):
            self.vel = [Vector2(2,0),Vector2(-2,0),Vector2(0,2),Vector2(0,-2)][int(random()*4)]

def thingAtPos(pos):
    tile_pos = Vector2(int(pos.x/32),int(pos.y/32))
    return map[tile_pos.y][tile_pos.x]

# initializate stuff
pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode([32*19,32*22])
points_in_unit_circle_border = [Vector2(cos(float(a)/8*2*pi),sin(float(a)/8*2*pi)) for a in xrange(8)]
things = []
dynamic_things = []
exit = False

map =  [[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
        [1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1],
        [1,0,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,0,1],
        [1,0,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,0,1],
        [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
        [1,0,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,0,1],
        [1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1],
        [1,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,1],
        [1,1,1,1,0,1,0,0,0,0,0,0,0,1,0,1,1,1,1],
        [1,1,1,1,0,1,0,1,1,0,1,1,0,1,0,1,1,1,1],
        [1,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1],
        [1,1,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,1,1],
        [1,1,1,1,0,1,0,0,0,0,0,0,0,1,0,1,1,1,1],
        [1,1,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,1,1],
        [1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1],
        [1,0,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,0,1],
        [1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1],
        [1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1],
        [1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1],
        [1,0,1,1,1,1,1,1,0,1,0,1,1,1,1,1,0,0,1],
        [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
        [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]]


#create pacman, walls, ghosts
pacman = Pacman()
for y in xrange(len(map)):
    for x in xrange(len(map[y])):
        if (map[y][x]==1):
            map[y][x] = Wall(Vector2(x*32+16,y*32+16))
for i in xrange(4):
    Ghost()

while exit==False:
    clock.tick(45)

    screen.fill([255,255,255])
    keyPressed = pygame.key.get_pressed()

    # events
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit = True
        if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE:
            exit = True

    # more ghosts
    if random()<0.001: Ghost()

    # updates e draws
    for thing in things:
        thing.update()
        thing.draw(screen)

    # collisions
    for A in dynamic_things:
        #dynamic vs dynamic
        for B in dynamic_things:
            if A!=B and abs(A.pos-B.pos)<(A.r+B.r):
                A.collide(B)
                B.collide(A)
        #dynamic vs walls
        for circle_point in points_in_unit_circle_border:
            thing_in_a_border = thingAtPos(A.pos+circle_point*12)
            if isinstance(thing_in_a_border,Wall):
                A.collide(thing_in_a_border)

    pygame.display.flip()

pygame.quit ()