Pygame启动画面崩溃游戏

时间:2014-05-18 12:38:45

标签: python python-3.x pygame splash-screen

这已经过编辑,原帖是关于blitting启动画面 我正在使用pygame开发一个简单的游戏,游戏几乎已经完成但是我在启动画面时遇到了一些问题。当前的问题是,当游戏运行时,启动画面会像他们应该的那样轻弹,但是如果用户点击屏幕上的任何地方或试图退出游戏,它就会崩溃。有没有人知道解决这个问题的方法,我希望用户甚至可以退出游戏,甚至可以在显示时跳过启动画面。

def main():
    '''Here the game is being initialised'''
    pygame.init() #Initialising Pygame
    pygame.key.set_repeat(1, 20) #Registers event every 20MS if a key is held down
    countFont = pygame.font.Font(None,18) #Font being set
    statusFont = pygame.font.Font(None,18) #Font being set
    screen = pygame.display.set_mode([WINDOW_WIDTH, WINDOW_HEIGHT]) 
    pygame.display.set_caption('Do Not Get Capped')

    #Drawable surface
    background = pygame.Surface(screen.get_size())

    #Used for converting color maps
    background = background.convert()

    #Splashscreen

    #image fades in
    for i in range (225):
            background.fill((0,0,0))
            image = pygame.image.load("splash_screen1.png")
            image.set_alpha(i)
            logoimage = screen.blit(image,(0,0))
            pygame.display.flip()

    pygame.time.delay(2000)

    for i in range (225):
            background.fill((0,0,0))
            image = pygame.image.load("splash_screen2.png")
            image.set_alpha(i)
            logoimage = screen.blit(image,(0,0))
            pygame.display.flip()

    pygame.time.delay(4000)        

    '''The main function which is called at the end of this code'''
    class Game():
            '''This class's purpose is to keep track of the current score'''
            def __init__(self):
                    self.score=0
                    self.goalNumbers=0

    class Gun(pygame.sprite.Sprite): 
            '''This is the gun that the user controls'''
            def __init__(self): 
                    '''This is the class contructor'''
                    pygame.sprite.Sprite.__init__(self)
                    self.image=pygame.image.load("turret.png") #Loading the gun's image
                    self.rect = self.image.get_rect() #Getting the image's Rect
                    self.rect.x = 240 #Setting the rect's X position
                    self.rect.y = 630 #Setting the rect's Y position

            def moveGun(self,orientation):
                    '''This function allows the gun to move on the screen.
                        If the orientation is facing left and the gun is 5 pixels
                         away from the wall, the gun is moved left & vice-a-versa'''
                    if orientation=="left" and self.rect.x>5: 
                            self.rect.x-=5
                    if orientation=="right" and self.rect.x<(480-self.rect.width):
                            self.rect.x+=5

    class Projectile(pygame.sprite.Sprite):
            '''This class sets up the projectile/bullets that are controlled
                by the user'''
            def __init__(self,gun):
                    pygame.sprite.Sprite.__init__(self)
                    self.image=pygame.image.load("bullet.png")
                    self.rect=self.image.get_rect()
                    '''The code below places the projectile on top of the gun'''
                    self.rect.x=gun.rect.x+(gun.rect.width/2)-(self.rect.width/2)
                    self.rect.y=gun.rect.y-gun.rect.height

            def updateProjectile(self):
                    '''This checks if the projectile has reached the top of the screen
                        if it hasn't it will continue to move up. If it has it will be deleted'''
                    if self.rect.y>0-self.rect.height:
                            self.rect.y-=5
                    else:
                            self.kill()

    class Objects(pygame.sprite.Sprite):
            '''This class creates the objects, they are loaded from the computer
                and assigned to variables'''
            def __init__(self):
                    pygame.sprite.Sprite.__init__(self)
                    self.obj=random.randint(1,3) 
                    if self.obj==1: imagefile="capped"
                    if self.obj==2: imagefile="notcapped1"
                    if self.obj==3: imagefile="notcapped2"
                    self.image=pygame.image.load(imagefile+".png")
                    self.rect=self.image.get_rect()
                    self.rect.y=-0-self.rect.height
                    self.rect.x=(random.randint(2,44)*10)

            def updateProjectile(self,game):
                    '''This function allows for the objects to move down the screen'''
                    if self.rect.y<640:
                            self.rect.y+=7 #This controls the amount of pixels the objects move down thus contrlling the speed
                    else:
                            if self.obj==1:
                                    '''Here the code is tracking the users score'''
                                    game.score+=10 #This adds 10 to the game's score
                                    game.goalNumbers+=1 
                            else:
                                    game.score-=50
                            self.kill()

            def shot(self,game):
                    '''This function updates the score as well as removing the objects when they are hit by a projectile'''
                    if self.obj == 1:
                            game.score-=50
                    else:
                            game.score+=10
                    self.kill()


    # Create initial object instances
    '''Here i am creating objects based on the classes i created'''
    game=Game()
    gun=Gun()
    sprites=pygame.sprite.Group()
    sprites.add(gun)
    obstacles=pygame.sprite.Group()
    projectiles=pygame.sprite.Group()
    '''This variable will be used to control when to come out of the loop, i will state when this happens belows'''
    finish=False
    clock=pygame.time.Clock() #Initialising the clock
    tick=0

    '''This is the start of the main while loop, this loop will continue
        until the variable 'finish' becomes false'''
    while finish == False:
            clock.tick(30) #Loop will run 30 times a second
            tick+=1
            screen.fill(bColour)

            '''Here the main events are being run'''
            for event in pygame.event.get():
                    if event.type==pygame.QUIT: 
                            '''If the user clicks the exit button, the finish variable is made True,
                                this means that rather than exiting the game, the user's score is displayed after
                                 which the game closes'''
                            finish = True
                    if event.type==pygame.KEYDOWN:
                            '''Here the script is checking for KEYDOWN events, these are events triggered
                                when the user presses on a keyboard key. In this case events are triggered when the left, right 
                                 and space keys are pressed.'''
                            if event.key==pygame.K_LEFT:
                                    gun.moveGun("left") #If this is activated the 'orientation' changes to 'left' which shunts the gun 5 pixels to the left
                            if event.key==pygame.K_RIGHT:
                                    gun.moveGun("right") #'Orientation' changes to 'right' which shunts the gun 5 pixels to the right
                            if event.key==pygame.K_SPACE:
                                    '''This triggers the projectiles function'''
                                    projectile=Projectile(gun)
                                    projectiles.add(projectile)       

            '''This controls the projectiles and objects moving around the window'''
            for projectile in projectiles:
                    projectile.updateProjectile()

            for obstacle in obstacles:
                    obstacle.updateProjectile(game)

            if tick>60: 
                    '''This controls at what rate the objects fall which is now once every two
                        seconds, this is because the loop runs in 30 second intervals and the 
                         clock is ticking at 60 seconds'''
                    if len(obstacles)<10:
                            obstacle=Objects()
                            obstacles.add(obstacle)
                    tick=0

            collisions=pygame.sprite.groupcollide(obstacles,projectiles,False,True)
            '''Here the script is checking whether the objects are hit by a projectile
               if they are, the 'shot' function is triggered'''
            if collisions: 
                    for obstacle in collisions:
                            obstacle.shot(game)

            '''This block of code constantly updates the player's scores'''                
            scoreText=countFont.render('Your current score is:'+str(game.score),True,(255,255,255),bColour)
            screen.blit(scoreText,(0,620))
            statusText=statusFont.render('You have '+str(10-game.goalNumbers)+' more tries',True,(255,255,255),bColour)
            screen.blit(statusText,(0,10))

            '''This code below updates and blits the objects to the screen'''
            sprites.draw(screen)
            projectiles.draw(screen)
            obstacles.draw(screen)
            pygame.display.flip()
            if game.goalNumbers>=10: 
                    '''This if statement is checking whether 'obj1' has touched the floor 10 times
                        and if it did, the finish variable is made true thus ending the game'''
                    finish=True

    '''This is the last piece of code visible to the user,
        what happens here is that the final message showing the final score is shown'''
    scoreCountHolder=pygame.image.load("scoreframe.png")
    scoreCountHolder.convert_alpha()
    left=90
    top=250
    screen.blit(scoreCountHolder,(left,top))
    countFont=pygame.font.Font(None,52)
    statusText=countFont.render('Your Score:'+str(game.score),True,bColour,(255,255,255))
    screen.blit(statusText,(105,300))
    pygame.display.flip() 

    while True: 
            '''This waits for the user to quit the game'''
            for event in pygame.event.get():
                    if event.type==pygame.QUIT:
                            sys.exit()

if __name__ == '__main__':
        '''The main function being called'''
        main()

2 个答案:

答案 0 :(得分:1)

当你有一个pygame应用程序时,你从输入队列中获取所有事件。

操作系统将新事件添加到队列中,同时应用程序将其删除。

由于您不删除事件,操作系统会认为您的应用程序冻结。

要解决此问题,您应致电pygame.event.pump()

来自pygame docs:

  

对于游戏的每一帧,您都需要进行某种调用   到事件队列。这可确保您的程序可以进行内部交互   与其余的操作系统。如果你没有使用其他   游戏中的事件函数,你应该调用pygame.event.pump()来   允许pygame处理内部操作。

     

如果您的程序一致,则无需此功能   通过另一个pygame.eventpygame处理队列上的事件   用于与事件和队列函数交互的模块。

     

有一些重要的事情必须在内部处理   事件队列。主窗口可能需要重新绘制或响应   系统。如果您也无法调用事件队列   很长时间,系统可能会决定你的程序已被锁定。

答案 1 :(得分:0)

你发了一个框架,然后Pygame希望你把平时发生的事件从事件队列中取出来。如果你不想操作系统认为那个应用程序卡住了!

如果要允许用户跳过闪屏,则需要在显示启动画面时处理事件。

以下是解决该问题的方法,它允许您为启动画面添加特定的事件处理:

class SplashScreen(object):
    def __init__(self):
        super().__init__()
        # Use numbers for ordering, make them continuous.
        self.image_dict = {
            1: "splash_screen1.png",
            2: "splash_screen2.png",
        }
        # Current image we are on!
        self.current_index = min(self.image_dict)
        # Last image
        self.end_index = max(self.image_dict)

        # Minimum alpha value
        self.alpha_min = 0
        # Maximum alpha value
        self.alpha_max = 225
        # Current alpha value
        self.alpha = self.alpha_min

        self.show = True

    # I leave it to you to figure out this function.
    def get_image(self):
        image_name = self.image_dict[self.current_index]
        image = pygame.image.load(image_name)
        image.set_alpha(self.alpha)
        self.alpha += 1
        if self.alpha > self.alpha_max:
            self.alpha = self.alpha_min
            self.current_index += 1
            if self.current_index == self.end_index:
                self.show = False
        return image


splash_screen = SplashScreen()

while True:
    # The ever-green event handling loop!
    for event in pygame.event.get():
        ...

    if splash_screen.show:
        # Splash screen stuff, one frame at a time
        background.fill((0, 0, 0))
        img = splash_screen.get_image()
        screen.blit(img, (0, 0))
    else:
        # Game stuff, no need to call display.flip here, called at the end.
        ...

    # Called at the end after frame is ready!
    pygame.display.flip()

离开练习
您应该在image_dict的{​​{1}}中加载并添加已加载的图片。每次进行blit时都不要从磁盘重新加载图像,这不是一个好主意。