简体   繁体   中英

GameOver screen not appearing when i want - pygame

I'm having a problem with finding a way to blit the GameOver screen at the right time. I made a platformer on pygame and i want the Game Over screen to appear after the animation of my character dying has occurred and when the enemy has had his attack animation. Right now it bypasses any animation and as soon as the collision detection between sprites is true, it says Game Over. Any ideas?

Thanks

def GameOver():

    intro = True

    while intro:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

        screen.blit(pygame.image.load("background0.jpg").convert(), (0,0))
        largeText = pygame.font.SysFont("elephant",60)
        TextSurf, TextRect = text_objects("GameOver", largeText)
        TextRect.center = ((screen_width/2),(screen_height/2))
        screen.blit(TextSurf, TextRect)

        pygame.display.update()
        clock.tick(15)


class Enemy:
    def __init__(self,x,y):

        self.x=x
        self.y=y
        self.width=40
        self.height = 40
        self.speed=1
        self.s0 = pygame.image.load("Images/Enemy/s0.png")
        self.s1 = pygame.image.load("Images/Enemy/s1.png")
        self.s2 = pygame.image.load("Images/Enemy/s2.png")
        self.s3 = pygame.image.load("Images/Enemy/s3.png")
        self.attack = pygame.image.load("attack.png")
        self.RotatedAttack = pygame.transform.flip(self.attack ,True,False)
        self.rotateds0 = pygame.transform.flip(self.s0 ,True, False)
        self.rotateds1 = pygame.transform.flip(self.s1 ,True, False)
        self.rotateds2 = pygame.transform.flip(self.s2 ,True, False)
        self.rotateds3 = pygame.transform.flip(self.s3 ,True, False)

        self.collision = False
        self.collision1 = False

        self.TimeTarget=10

        self.TimeNum=0

        self.currentImage=0

    def move(self,player):

        if self.x > player.x:
            self.x -= self.speed
            if self.currentImage > 3:
                self.currentImage = 0
            if self.collision == True:

                if self.currentImage < 4:
                    #image of him attacking
                    self.currentImage = 8
                    SpearAttack.play(loops = 0, maxtime = 10)                

        elif self.x < player.x:
            self.x += self.speed
            if self.currentImage < 4:    
                self.currentImage = 4
            if self.collision == True:
                if player.y > 487:

                    if self.currentImage == 4 or 5 or 6 or 7:
                        #image of him attacking flipped
                        self.currentImage = 9
                        SpearAttack.play(loops = 0, maxtime = 10)
                        #Tried putting gameover here but it skips the animation

        if self.x < player.x:
            if self.x > player.x:
                if self.currentImage > 3:
                    self.currentImage = 0       

    def update(self,CollisionDetect,player,enemy2):

        self.TimeNum+=1
        if self.TimeNum == self.TimeTarget:

            if self.currentImage ==0:
                self.currentImage=1

            elif self.currentImage ==1:
                self.currentImage=2

            elif self.currentImage == 2:
                self.currentImage=3

            elif self.currentImage ==3:
                self.currentImage =0

            elif self.currentImage ==4:
                self.currentImage=5

            elif self.currentImage ==5:
                self.currentImage=6

            elif self.currentImage == 6:
                self.currentImage=7

            elif self.currentImage ==7:
                self.currentImage = 4

            self.TimeNum=0

        if self.currentImage==0:

            screen.blit(self.s0, (self.x,self.y))

        elif self.currentImage==1:
            screen.blit(self.s1, (self.x,self.y))

        elif self.currentImage==2:
            screen.blit(self.s2, (self.x,self.y))

        elif self.currentImage ==3:
            screen.blit(self.s3, (self.x,self.y))

        elif self.currentImage==4:
            screen.blit(self.rotateds0, (self.x,self.y))

        elif self.currentImage==5:
            screen.blit(self.rotateds1, (self.x,self.y))

        elif self.currentImage==6:
            screen.blit(self.rotateds2, (self.x,self.y))

        elif self.currentImage ==7:
            screen.blit(self.rotateds3, (self.x,self.y))

        elif self.currentImage ==8:
            screen.blit(self.attack, (self.x,self.y))
            #tried putting GameOver() here but it skips the blit.
        elif self.currentImage ==9:
            screen.blit(self.RotatedAttack, (self.x,self.y))

        self.collision = CollisionDetect(self.x,self.y,self.width,self.height,player.x,player.y,player.width,player.height)

I'd say you have to delay the animation. It seems that pygame doesn't have a default animation queue, therefore you'll have to take care of it. There are a few things that could actually work:

  • Using time.sleep() - this wont work however if the animation is part of the single thread, since the entire thread will be stopped (and the animation should freeze). Therefore I'll recommend the second option since it sounds more reasonable for me.

  • Using the pygame timer pygame.time.set_timer() , which should be a thread and therefore not freeze the spear-animation. You'll have to send a gameover event which will then be caught inside your gameover function and reset the timer for that event to 0 (to stop the loop) once it's caught. https://www.pygame.org/docs/ref/time.html#comment_pygame_time_set_timer

  • Using a thread (see: Python threading.timer - repeat function every 'n' seconds ) and simply calling that thread with the timer after your spear-animation

The following has nothing to do with the error itself but your code is poorly designed in general so this might help: You are trying to call a function from the game (in this case gameover) from an instance of the class (in this case enemy), which is a bad practice and semantically incorrect. The Enemy-Class shouldn't know the game at all, it should however be used by the game - not the other way around. It can fire certain events, but a different, global handler should take care of when the game is over (and similar game-related events), not a single instance of a class.

Also, instead of having endless if-else conditions you should consider using some kind of mapping - for example a dictionary. It'll safe you many lines of code, it's easier to maintain and also more readable.

I found the issue, and it isn't an issue with delays or anything like that, it's an issue with your code.

Where it has the following code:

if self.currentImage == 4 or 5 or 6 or 7:
    #image of him attacking flipped
    self.currentImage = 9
    SpearAttack.play(loops = 0, maxtime = 10)
    #Tried putting gameover here but it skips the animation

Put gameover there. Here is the line of code that has the issue:

if self.currentImage == 4 or 5 or 6 or 7:

Python does not work that way. Saying that will always return true. You are thinking that is the same as:

if self.currentImage == 4 or self.currentImage == 5 or self.currentImage == 6 or self.currentImage == 7:

It is not. You are saying this:

if (self.currentImage == 4) or (5) or (6) or (7):

Any integer other than 0 always returns true.

Try the following line of code, this should work:

if self.currentImage in [4,5,6,7]:

Have fun Pygaming! (If that's a word)

Usually when you define something you call it or the function, you should import time :

import time

Then after the animation do:

time.sleep(0.5)
GameOver()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM