为什么我的pygame游戏这么慢?

时间:2013-10-08 11:16:01

标签: python pygame

在我的游戏中有一个地形生成器,随后产生了许多实例..但我实现了一个代码:

for b in blocklist:
    if b.rect.left>=0:
       if b.rect.right<=640:
          screen.blit(b.sprite, b.rect)

因此它只在scree(400-500)块内渲染事物,并且它仍然运行,好像它渲染全部2000左右。那么我做错了什么?它与

有什么关系吗?
pygame.display.update() #or
pygame.display.flip()

他们的差别是什么?

以下是代码:

   #Init stuff
   import pygame,random
   from pygame.locals import *
   from collections import namedtuple
   import time, string
   pygame.mixer.init(frequency=22050, size=-16, channels=2, buffer=500)
   f=open('texdir.txt','r')
   texdir=f.read()
   f.close()
   f=open(texdir+"\\splash.txt",'r')
   splash=f.read()
   splash=splash.replace('(','')
   splash=splash.replace(')','')
   splash=splash.split(',')
   f.close()
   splashlen=len(splash)
   chc=random.randint(0,int(splashlen))
   splash=splash[chc-1]
   f=open(texdir+"//backcolor.txt")
   pygame.init()
   clock=pygame.time.Clock()
   screen=pygame.display.set_mode((640,480))
   pygame.display.set_caption("PiBlocks | By Sam Tubb")
   max_gravity = 100
   blocksel=texdir+"\\dirt.png"
   btype='block'
   backimg = pygame.image.load(texdir+"\\menu.png").convert()
   backimg = pygame.transform.scale(backimg, (640,480))
   clsimg = pygame.image.load("clear.bmp").convert()
   clsimg = pygame.transform.scale(clsimg, (640,480))
   ingame=0
   sbtn=pygame.image.load("startbtn.png").convert()
   qbtn=pygame.image.load("quitbtn.png").convert()
   tbtn=pygame.image.load("texbtn.png").convert()
   sbtnrect=sbtn.get_rect()
   sbtnrect.x=220
   sbtnrect.y=190
   qbtnrect=qbtn.get_rect()
   qbtnrect.x=220
   qbtnrect.y=225
   tbtnrect=tbtn.get_rect()
   tbtnrect.x=220
   tbtnrect.y=260
   go=0
   gotime=35
   select=1
   colliding = False
   Move = namedtuple('Move', ['up', 'left', 'right'])
   player=[]
   blocklist=[]
   font=pygame.font.Font(None,18)

   #set cursor
   curs = pygame.image.load(texdir+"\\cursor.png").convert()
   curs.set_colorkey((0,255,0))

   #set backcolor
   COLOR=f.read()
   f.close()
   COLOR=COLOR.replace('(','')
   COLOR=COLOR.replace(')','')
   COLOR=COLOR.split(',')
   c1=COLOR[0]
   c2=COLOR[1]
   c3=COLOR[2]

   #load sounds
   place=pygame.mixer.Sound('sound\\place.wav')
   place2=pygame.mixer.Sound('sound\\place2.wav')
   place3=pygame.mixer.Sound('sound\\place3.wav')

   #set sprites and animation frames
   psprite = pygame.image.load(texdir+"\\player\\playr.png").convert()
   psprite.set_colorkey((0,255,0))
   psprite2 = pygame.image.load(texdir+"\\player\\playr2.png").convert()
   psprite2.set_colorkey((0,255,0))
   psprite3 = pygame.image.load(texdir+"\\player\\playr3.png").convert()
   psprite3.set_colorkey((0,255,0))
   anim=1
   class Block(object):
           def __init__(self,x,y,sprite,btype):
                   if blocksel==texdir+"\\woodslab.png":
                          self.btype='slab'
                          self.sprite = pygame.image.load(sprite).convert()
                          self.rect = self.sprite.get_rect(top=y+16, left=x)
                   else:
                          self.btype='block'
                          self.sprite = pygame.image.load(sprite).convert_alpha()
                          self.rect = self.sprite.get_rect(top=y, left=x)


   class Player(object):
       sprite=psprite
       def __init__(self, x, y):
           self.rect = self.sprite.get_rect(centery=y, centerx=x)
           # indicates that we are standing on the ground
           # and thus are "allowed" to jump
           self.on_ground = True
           self.xvel = 0
           self.yvel = 0
           self.jump_speed = 7
           self.move_speed = 3

       def update(self, move, blocks):

           # check if we can jump 
           if move.up and self.on_ground:
               self.yvel -= self.jump_speed

           # simple left/right movement
           if move.left:
                   self.xvel = -self.move_speed
           if move.right:
                   self.xvel = self.move_speed

           # if in the air, fall down
           if not self.on_ground:
               self.yvel += 0.3
               # but not too fast
               if self.yvel > max_gravity: self.yvel = max_gravity

           # if no left/right movement, x speed is 0, of course
           if not (move.left or move.right):
               self.xvel = 0

           # move horizontal, and check for horizontal collisions
           self.rect.left += self.xvel
           self.collide(self.xvel, 0, blocks)

           # move vertically, and check for vertical collisions
           self.rect.top += self.yvel
           self.on_ground = False;
           self.collide(0, self.yvel, blocks)

       def collide(self, xvel, yvel, blocks):
           # all blocks that we collide with
           for block in [blocks[i] for i in self.rect.collidelistall(blocks)]:

               # if xvel is > 0, we know our right side bumped 
               # into the left side of a block etc.
               if xvel > 0:
                       self.rect.right = block.rect.left
               if xvel < 0:
                       self.rect.left = block.rect.right

               # if yvel > 0, we are falling, so if a collision happpens 
               # we know we hit the ground (remember, we seperated checking for
               # horizontal and vertical collision, so if yvel != 0, xvel is 0)
               if yvel > 0:
                   self.rect.bottom = block.rect.top
                   self.on_ground = True
                   self.yvel = 0
               # if yvel < 0 and a collision occurs, we bumped our head
               # on a block above us
               if yvel < 0: self.rect.top = block.rect.bottom

   def get_key():
     while 1:
       event = pygame.event.poll()
       if event.type == KEYDOWN:
         return event.key
       else:
         pass

   def display_box(screen, message):
     "Print a message in a box in the middle of the screen"
     fontobject = pygame.font.Font(None,18)
     pygame.draw.rect(screen, (0,0,0),
                      ((screen.get_width() / 2) - 100,
                       (screen.get_height() / 2) - 10,
                       200,20), 0)
     pygame.draw.rect(screen, (255,255,255),
                      ((screen.get_width() / 2) - 102,
                       (screen.get_height() / 2) - 12,
                       204,24), 1)
     if len(message) != 0:
       screen.blit(fontobject.render(message, 1, (255,255,255)),
                   ((screen.get_width() / 2) - 100, (screen.get_height() / 2) - 10))
     pygame.display.flip()

   def ask(screen, question):
     "ask(screen, question) -> answer"
     pygame.font.init()
     current_string = []
     display_box(screen, question + ": " + string.join(current_string,""))
     while 1:
       inkey = get_key()
       if inkey == K_BACKSPACE:
         current_string = current_string[0:-1]
       elif inkey == K_RETURN:
         break
       elif inkey == K_MINUS:
         current_string.append("_")
       elif inkey <= 127:
         current_string.append(chr(inkey))
       display_box(screen, question + ": " + string.join(current_string,""))
     return string.join(current_string,"")
   while True:
           for block in blocklist:
                   if any(block.rect.colliderect(b.rect) for b in blocklist if b is not block):
                           if b.btype=='slab':
                                   blocklist.remove(block)
                           else:
                                   blocklist.remove(b)
           if ingame==1:
               screen.fill((int(c1),int(c2),int(c3)))
               mse = pygame.mouse.get_pos()
               key = pygame.key.get_pressed()
               if key[K_a]:
                       anim+=1
                       if anim==9:
                               anim=1
               if key[K_d]:
                       anim+=1
                       if anim==9:
                               anim=1
               if key[K_1]:
                   blocksel=texdir+"\\dirt.png"
                   btype='block'
                   select=1
               if key[K_2]:
                   blocksel=texdir+"\\stonetile.png"
                   btype='block'
                   select=2
               if key[K_3]:
                   blocksel=texdir+"\\stone.png"
                   btype='block'
                   select=3
               if key[K_4]:
                   blocksel=texdir+"\\sand.png"
                   btype='block'
                   select=4
               if key[K_5]:
                   blocksel=texdir+"\\woodplank.png"
                   btype='block'
                   select=5
               if key[K_6]:
                   blocksel=texdir+"\\woodslab.png"
                   btype='slab'
                   select=6
               if key[K_LEFT]:
                   try:
                           for b in blocklist:
                               b.rect.left+=32
                   except:
                           pass
                   try:
                           player.rect.left+=32
                   except:
                           pass
               if key[K_RIGHT]:
                       try:
                           for b in blocklist:
                               b.rect.left-=32
                       except:
                               pass
                       try:
                           player.rect.left-=32
                       except:
                               pass
               if key[K_UP]:
                       try:
                           for b in blocklist:
                               b.rect.top+=32
                       except:
                               pass
                       try:
                           player.rect.top+=32
                       except:
                               pass
               if key[K_DOWN]:
                       try:
                           for b in blocklist:
                               b.rect.top-=32
                       except:
                               pass
                       try:
                           player.rect.top-=32
                       except:
                               pass
               if key[K_ESCAPE]:
                   execfile('PiBlocks.pyw')
               for event in pygame.event.get():
                   if event.type == QUIT:
                       exit()
                   if event.type == MOUSEBUTTONDOWN:
                           if event.button==4:
                                   if select<9:
                                           select=select+1
                                   else:
                                           select=1
                           elif event.button==5:
                                   if select>1:
                                           select=select-1
                                   else:
                                           select=9
                           if select==1:
                                   blocksel=texdir+"\\dirt.png"
                                   btype='block'
                           if select==2:
                                   blocksel=texdir+"\\stonetile.png"
                                   btype='block'
                           if select==3:
                                   blocksel=texdir+"\\stone.png"
                                   btype='block'
                           if select==4:
                                   blocksel=texdir+"\\sand.png"
                                   btype='block'
                           if select==5:
                                   blocksel=texdir+"\\woodplank.png"
                                   btype='block'
                           if select==6:
                                   blocksel=texdir+"\\woodslab.png"
                                   btype='slab'


                   if key[K_LSHIFT]:
                       if event.type==MOUSEMOTION:
                           if not any(block.rect.collidepoint(mse) for block in blocklist):
                               snd=random.randint(1,3)
                               x=(int(mse[0]) / 32)*32
                               y=(int(mse[1]) / 32)*32
                               if go==1:
                                           if snd==1:
                                               place.play()
                                           elif snd==2:
                                               place2.play()
                                           elif snd==3:
                                               place3.play()
                                           blocklist.append(Block(x,y,blocksel,btype))
                   if key[K_RSHIFT]:
                       if event.type==MOUSEMOTION:
                           to_remove = [b for b in blocklist if b.rect.collidepoint(mse)]
                           for b in to_remove:
                                   if go==1:
                                           blocklist.remove(b)
                   else:
                       if event.type == pygame.MOUSEBUTTONUP:
                           if event.button == 1:
                               to_remove = [b for b in blocklist if b.rect.collidepoint(mse)]
                               for b in to_remove:
                                   if go==1:
                                           blocklist.remove(b)

                               if not to_remove:
                                   snd=random.randint(1,3)
                                   x=(int(mse[0]) / 32)*32
                                   y=(int(mse[1]) / 32)*32
                                   if go==1:
                                           if snd==1:
                                               place.play()
                                           elif snd==2:
                                               place2.play()
                                           elif snd==3:
                                               place3.play()
                                           blocklist.append(Block(x,y,blocksel,btype))

                           elif event.button == 3:
                               x=(int(mse[0]) / 32)*32
                               y=(int(mse[1]) / 32)*32
                               player=Player(x+16,y+16)

               move = Move(key[K_w], key[K_a], key[K_d])

               for b in blocklist:
                       if b.rect.left>=0:
                               if b.rect.right<=640:
                                       screen.blit(b.sprite, b.rect)

               if player:
                   player.update(move, blocklist)
                   if anim==1 or anim==2 or anim==3:
                           screen.blit(psprite, player.rect)
                   elif anim==4 or anim==5 or anim==6:
                           screen.blit(psprite2, player.rect)
                   elif anim==7 or anim==8 or anim==9:
                           screen.blit(psprite3, player.rect)
               x=(int(mse[0]) / 32)*32
               y=(int(mse[1]) / 32)*32
               screen.blit(curs,(x,y))
               clock.tick(60)
               x=blocksel.replace(texdir,'')
               x=x.replace('.png','')
               vers=font.render('PiBlocks Alpha 0.6',True,(255,255,255))
               tex=font.render('Selected Texture Pack: '+texdir,True,(255,255,255))
               words=font.render('Selected Block: '+str(x), True, (255,255,255))
               screen.blit(vers,(1,1))
               screen.blit(tex,(1,12))
               screen.blit(words,(1,25))
               if gotime==0:
                       go=1
               else:
                       gotime-=1
               pygame.display.update()
           elif ingame==0:
                   blocklist=[]
                   mse = pygame.mouse.get_pos()
                   player=[]
                   key = pygame.key.get_pressed()
                   text=font.render(splash, True, (255,255,255))
                   if key[K_RETURN]:
                           ingame=1
                   for event in pygame.event.get():
                           if event.type == QUIT:
                               exit()
                           if event.type == KEYDOWN:
                                   print event.key
                   if sbtnrect.collidepoint(mse):
                           if pygame.mouse.get_pressed()==(1,0,0):
                                   ingame='gen'
                                   top=(random.randint(5,8)*32)
                                   cen=(top+random.randint(4,6)*32)
                                   down=15
                                   across=0
                                   blklvl=0
                                   while across<1920:
                                           while down>0:
                                                   screen.fill((0,0,0))
                                                   if blklvl==top:
                                                           blocklist.append(Block(across,blklvl,texdir+"\\grass.png",'block'))
                                                   if blklvl>top:
                                                           if blklvl<cen:
                                                                   blocklist.append(Block(across,blklvl,texdir+"\\dirt.png",'block'))
                                                   if blklvl>cen-1:
                                                           blocklist.append(Block(across,blklvl,texdir+"\\stone.png",'block'))
                                                   down=down-1
                                                   blklvl=blklvl+32

                                           if down==0:
                                                   if across<1920:
                                                           per=(across/(32/5))
                                                           if per>100:
                                                                   per=100
                                                           top=(random.randint(5,8)*32)
                                                           cen=(top+random.randint(4,6)*32)
                                                           down=15 
                                                           blklvl=0
                                                           across=across+32
                                                           down=15
                                                           drawgen=font.render('GENERATION:'+str(per)+'%%', True, (255,255,255))
                                                           screen.blit(drawgen,(1,1))
                                                           pygame.display.flip()
                                           go=0
                                           ingame=1

                   if qbtnrect.collidepoint(mse):
                           if pygame.mouse.get_pressed()==(1,0,0):
                                   exit()
                   if tbtnrect.collidepoint(mse):
                           if pygame.mouse.get_pressed()==(1,0,0):
                                   ingame='texsel'
                   screen.blit(backimg,(0,0))
                   screen.blit(text,(364,76))
                   screen.blit(sbtn,sbtnrect)
                   screen.blit(qbtn,qbtnrect)
                   screen.blit(tbtn,tbtnrect)
                   pygame.display.flip()
           elif ingame=='texsel':
                    screen.blit(clsimg,(0,0))
                    inp = ask(screen, 'Texture Directory')
                    f=open('texdir.txt','w')
                    f.write(str(inp))
                    f.close()
                    pygame.display.flip()
                    execfile('PiBlocks.pyw')

非常感谢任何帮助

1 个答案:

答案 0 :(得分:8)

代码运行缓慢,因为它是一堆非结构化代码(此 已清理的版本),它不断加载外部资源,读取事件和鼠标数据。

  1. 构建您的代码,以便从文件中读取缓慢的内容 ONCE
  2. 同样为每个块读取密钥,事件等
  3. 请记住以下内容:if if if是否进行了大量操作,如果elif elif elif在第一次成功结束 dict.get()通常要快得多,那么您的代码可以查找要在按键上执行的操作,并执行操作 - 如果操作是在函数中执行的。
  4. 阅读有关状态引擎以及如何使用它们的信息!