0

我已经从主循环中删除了所有可能的内容。我还优化了动态和静态对象的碰撞,大大减少了迭代次数。但是在他的机器上它仍然很慢。我会为有人想要测试它的情况发布整个文件,但您可以在“while Exit==false:”处跳转到主循环。

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 ()
4

2 回答 2

2

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

当然,您需要为此停止每一帧都使屏幕空白,并且要对要更新的内容进行大量管理。在 pygame http://www.pygame.org/docs/ref/sprite.html#pygame.sprite.DirtySprite中有一些对脏精灵的额外支持,可以帮助您。或者您可以通过将它们所在的位置消隐并将它们重新绘制到新位置(显然这两个区域中的所有内容)来更新所有“活动”精灵。在列表中收集受影响的矩形并将其传递给 update_rects() 而不是翻转屏幕。应该没有必要在吃豆人游戏中每一帧都画墙……

于 2012-05-04T16:14:16.157 回答
0

可能不是缓慢的主要来源,但是“while exit==False:”需要比“while not exit:”多一点的字节码来执行。

于 2012-04-30T18:50:50.623 回答