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