pygame.event.set_grab在异常/崩溃后保持打开状态,并使程序“无法启动”

时间:2018-08-17 18:23:13

标签: python python-3.x pygame

我正在使用 pygame 创建游戏,并且正在使用 pygame.event.set_grab(True)将光标保持在游戏窗口中(它保持所有键盘输入)在窗口中也是如此),但是当程序崩溃(由于语法错误或其他异常)时,set_grab保持打开状态,以后无法关闭程序。 (幸运的是我正在使用Linux,所以我可以访问覆盖所有内容的控制台,因此可以手动将其关闭) 我想知道是否有可能进行一些错误处理以将其关闭(或杀死程序),或者是否有更好的方法将 just 鼠标输入保留在窗口中。 (因此可以使用alt + f4)

import pygame
pygame.init()
size = (600, 700)
monitor=pygame.display.Info()  
screen = pygame.display.set_mode(size)#pygame.FULLSCREEN)
pygame.display.set_caption("Meteor Galaxy 3")
done = False
clock = pygame.time.Clock()
pygame.mouse.set_visible(0)
pygame.event.set_grab(True) #this is turned on with the  initialization
#(doesnt have to be) of the game

游戏崩溃时,它会变成通常的黑色窗口,但您无能为力。

谢谢。

编辑: 完整代码:

#coding: utf-8
import pygame
import random

random.randint(0,2)
#TODO: 
#Vymyslieť systém na čakanie framov
#Upraviť zmenu rýchlosti hráčovho náboja
##Pygame init
pygame.init()
size = (600, 700)
possible_sizes=[[600,700],[900,1050],[1200,1400],[1800,2100]]  #ASI 1200,1400 obrázky a potom downscale?? (ak vôbec zmena rozlisenia..)
monitor=pygame.display.Info()  
screen = pygame.display.set_mode(size)#pygame.FULLSCREEN)
pygame.display.set_caption("Meteor Galaxy 3")
done = False
clock = pygame.time.Clock()
pygame.mouse.set_visible(0)
pygame.event.set_grab(True)

#<VARIABLES>
##<COLORS>
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
RED = (255, 0, 0)
##</COLORS>
##<IMAGES> #"../meteo_data/img/"
bg1=[pygame.image.load("../meteo_data/img/bg1.png"),700-5770,True]

#backgrounds.append([pygame.image.load("img/bg2.png"),[600,1924]])
#backgrounds.append([pygame.image.load("img/bg3.png"),[600,1924]])
img_crosshair=pygame.image.load("../meteo_data/img/crosshair.png").convert()
#Ships
img_player=pygame.image.load("../meteo_data/img/ships/player.png").convert()
img_enemy1=pygame.image.load("../meteo_data/img/ships/enemy1.png").convert()
#Bullets
img_b1=pygame.image.load("../meteo_data/img/bullets/bullet.png").convert() 


img_player.set_colorkey(BLACK)
img_enemy1.set_colorkey(BLACK)
img_crosshair.set_colorkey(BLACK)
##</IMAGES>

##<SOUNDS>

##</SOUNDS>

menu_game=1 #Nula pre menu , jedna pre hru?? , medzi nula a jedna ostatné??
esc_menu=False
fire=False
level=-1
level_ended=True
##                                                         def=0 def=0
##<BULLET TYPES> #[IMAGE,DAMAGE,SPEED,PENETRATION,relX,relY] /relX a relY vziať z relX a relY lode.
B_default=[img_b1,3,4,False,0,0]
##</BULLET TYPES>

##<SHIP TYPES> #[IMAGE,HEALTH,SPEED,RELOAD,X,Y,relX,relY,BULLET_TYPE] /relX a relY je pre bullet

##</SHIP TYPES>

##<LEVELS>
level1=[bg1]

master_level=[level1]
##</LEVELS>
#</VARIABLES>


#<FUNCTIONS>
##<SPRITES>
class bullet(pygame.sprite.Sprite):
   def __init__(self,bullet_type):
      pygame.sprite.Sprite.__init__(self)
      self.image=bullet_type[0]
      self.dmg=bullet_type[1]
      self.speed=bullet_type[2]
      self.penetration=bullet_type[3] ##Prestrelí viac ENIMÁKOV ? True/False
      self.rect = self.image.get_rect()
      self.rect.x=bullet_type[4] ##Vypočítať pri vystrelení (ship pos -/+ ship.bullet_x(y)) (pre každý typ lode zvlášť)
      self.rect.y=bullet_type[5]
      self.image.set_colorkey(BLACK)

class ship(pygame.sprite.Sprite):
   def __init__(self,ship_type):
      pygame.sprite.Sprite.__init__(self)
      self.image=ship_type[0]
      self.hp=ship_type[1]
      self.speed=ship_type[2] ##0 Pre hráča
      self.reload=ship_type[3] ##Rýchlosť streľby (koľko framov čakať) 0 = každý frame bullet
      self.rect=self.image.get_rect()
      self.rect.x=ship_type[4]
      self.rect.y=ship_type[5]
      self.bullet_x=ship_type[6]
      self.bullet_y=ship_type[7]
      self.b_type=ship_type[8]
      self.image.set_colorkey(BLACK)
class barrier(pygame.sprite.Sprite):
   def __init__(self,coord):
      pygame.sprite.Sprite.__init__(self)
      self.image=pygame.Surface([700,40])
      self.image.fill(WHITE)
      self.rect=self.image.get_rect()
      self.rect.x=coord[0]
      self.rect.y=coord[1]

bullets=pygame.sprite.Group()
ships=pygame.sprite.Group()
barriers=pygame.sprite.Group()

player_b_type=B_default
player_b_type[2]=player_b_type[2]*(-1)
player=ship([img_player,100,0,10,279,650,15,3,player_b_type])  ##PLAYER SHIP
wait=player.reload
barrier_top=barrier([-50,-400])
barrier_bottom=barrier([-50,900])

barriers.add(barrier_top)
barriers.add(barrier_bottom)
##</SPRITES>


#</FUNCTIONS>

while not done:
   for event in pygame.event.get():
      if event.type == pygame.QUIT:
         done = True
      elif event.type == pygame.MOUSEBUTTONDOWN:
         if event.button==1:
            fire=True
      elif event.type == pygame.MOUSEBUTTONUP:
         if event.button==1:
            fire=False
      elif event.type==pygame.KEYDOWN:
         if event.key==pygame.K_ESCAPE:
            if not esc_menu:
               esc_menu=True
               pygame.event.set_grab(False)
            else:
               esc_menu=False
               pygame.event.set_grab(True)
   coord=pygame.mouse.get_pos()
   if menu_game==0:
      screen.fill(WHITE) #BG
   elif menu_game==1:
      #GAME LOGIC
      if level_ended:
          level=level+1
          bg1_y=master_level[level][0][1]
          level_ended=False
      bg1_y=bg1_y+2
      player.rect.x=coord[0]-20

      pygame.sprite.groupcollide(barriers,bullets,False,True)
      pygame.sprite.groupcollide(barriers,ships,False,True)
      if fire:
         if wait==0:
            bullet_modified=player.b_type
            bullet_modified[4]=player.rect.x+player.bullet_x
            bullet_modified[5]=player.rect.y+player.bullet_y
            b=bullet(bullet_modified)
            bullets.add(b)         
            wait=player.reload
         else:
            wait=wait-1
      #RENDERING
      screen.fill(BLACK)
      screen.blit(master_level[level][0][0],[0,bg1_y]) #BG
      screen.blit(player.image,player.rect)

      for naboj in bullets:
         screen.blit(naboj.image,naboj.rect)
         naboj.rect.y=naboj.rect.y+naboj.speed
      screen.blit(img_crosshair,[coord[0]-10,coord[1]-10])

   pygame.display.flip() #FRAMY
   clock.tick(60)
pygame.quit()

#NOTES:
# Dlzka lvl sa urci vyskou bg (5760 px == 48 sec - 1. lvl)
#189 - 
#

1 个答案:

答案 0 :(得分:2)

因此,问题在于,如果该代码的中间发生某些异常,则不会调用pygame.quit()

您要做的就是在Pygame代码周围设置一个try ... fynaly块,并将pygame.quit()调用放在finally块上。

为此,我建议进行一些重新格式化,这也将改善代码的模块化,即将您放在模块级别的所有代码封装在一个函数内。

所以:

...

def main():
    done = False
    while not done:
        ...
        for naboj in bullets:
            ...
            screen.blit(img_crosshair,[coord[0]-10,coord[1]-10])

        pygame.display.flip() #FRAMY
        clock.tick(60)

try:
    main()
finally:
    pygame.quit()

通过这种方式,在main中运行的代码中(或在从其调用的任何其他函数中)任何未处理的异常,以及行为良好的主循环终止,都将立即在{{ 1}}块:Pygame及其事件处理均已关闭,并且您在终端上获得了错误回溯,从而可以修复代码。

更新finally提示对于任何使用pygame使用全屏模式制作游戏的人也至关重要,无论event_grab如何。