繁体   English   中英

使用 Pygame 的游戏结束屏幕

[英]Game Over Screen using Pygame

我正在尝试完成一个版本的乒乓球,我希望当球员错过球并击中球拍后面的墙壁时比赛结束。 我一直在尝试为此构建一个 Game Over 屏幕,但没有运气。 我希望用户可以选择重新开始新游戏或一起退出屏幕。

# Import the pygame library and initialise the game 
# the scoring system will be inside of the main game
# the paddle and ball classes are imported into the main game
# still trying to work out how to make the other paddle move without keyboard input
import pygame
from Paddle import Paddle
from Ball import Ball
#while running loop
     #rest of the code

pygame.init()
black = (0,0,0)
white = (255,255,255)


paddle2 = Paddle(white, 10, 100)
paddle2.rect.x = 670
paddle2.rect.y = 200

ball = Ball(white,8,8)
ball.rect.x = 345
ball.rect.y = 195

width = 700
height = 500

size = (700, 500)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("Pong")

user_lose = False

sprites_list = pygame.sprite.Group()

sprites_list.add(paddle2)
sprites_list.add(ball)

carryOn = True

clock = pygame.time.Clock()

#Set inital player scores:
scoreA = 0
scoreB = 0



# -------- Main Program Loop -----------
while carryOn:
    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
              carryOn = False 
        elif event.type==pygame.KEYDOWN:
                if event.key==pygame.K_x: 
                     carryOn=False 


    keys = pygame.key.get_pressed()
    if keys[pygame.K_UP]:
        paddle2.up(5)
    if keys[pygame.K_DOWN]:
        paddle2.down(5)

    sprites_list.update()

    if ball.rect.x>=690:
        scoreA+=1
        ball.velocity[0] = -ball.velocity[0]
    if ball.rect.x<=0:
        scoreB+=1
        ball.velocity[0] = -ball.velocity[0]
    if ball.rect.y>490:
        ball.velocity[1] = -ball.velocity[1]
    if ball.rect.y<0:
        ball.velocity[1] = -ball.velocity[1]  

    if pygame.sprite.collide_mask(ball, paddle2):
        ball.bounce()

    screen.fill(black)

    sprites_list.draw(screen) 

    #Scores displayed:
    font = pygame.font.Font(None, 74)
    font2 = pygame.font.Font(None, 55)
    """
    text = font.render(str(scoreA), 1, white)
    screen.blit(text, (250,10))
    """
    text = font.render(str(scoreB), 1, white)
    screen.blit(text, (430,10))
    text = font.render(str("Score: "), 1 ,white)
    screen.blit(text, (250, 10))
    text = font2.render(str("Keep The Ball Bouncing"), 1, white)
    screen.blit(text, (155,60))

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

pygame.quit()

您可以使用变量state = 'INTRO'/'GAME'/'GAMEOVER'或分隔变量is_intro = True/False , is_game = True/False , is_gameover = True/False , is_pause = True/False来控制在 main 中执行的代码环形

它还需要使用global来重置外部/全局值的 function reset_all_values

像这样的东西。

import pygame

def reset_all_values():
    global scoreA
    global scoreB

    scoreA = 0
    scoreB = 0

    # reset other values

# --- main ---

size = (700, 500)

pygame.init()
screen = pygame.display.set_mode(size)

clock = pygame.time.Clock()

font = pygame.font.Font(None, 50)

reset_all_values()

# -------- Main Program Loop -----------

state = 'INTRO'

carry_on = True

while carry_on:

    # --- events ---

    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            carryOn = False 
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_x: 
                carry_on = False

            if state == 'INTRO':
                if event.key == pygame.K_ESCAPE:                    
                    state = 'GAME'
                    reset_all_values() # 
                # other keys for intro
            elif state == 'GAME':
                if event.key == pygame.K_ESCAPE: 
                    state = 'GAMEOVER'
                # other keys for game
            elif state == 'GAMEOVER':
                if event.key == pygame.K_ESCAPE: 
                    state = 'INTRO'
                    #reset_all_values() # TODO
                # other keys for gameover


    # --- changes/moves/collisions ---

    if state == 'INTRO':
        pass
    elif state == 'GAME':
        scoreA += 1
        if scoreA >= 100:
            state = 'GAMEOVER'
    elif state == 'GAMEOVER':
        pass

    # --- draws ---

    screen.fill((0,0,0))

    if state == 'INTRO':
        text = font.render('INTRO - Press ESC', True, (255,255,255))
        rect = text.get_rect(center=screen.get_rect().center)
        screen.blit(text, rect)
    elif state == 'GAME':
        text = font.render('GAME - Wait for Score 100', True, (255,255,255))
        rect = text.get_rect(center=screen.get_rect().center)
        screen.blit(text, rect)
        text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
        rect = text.get_rect()
        screen.blit(text, rect)
    elif state == 'GAMEOVER':
        text = font.render('GAMEOVER - Press ESC', True, (255,255,255))
        rect = text.get_rect(center=screen.get_rect().center)
        screen.blit(text, rect)
        text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
        rect = text.get_rect()
        screen.blit(text, rect)

    pygame.display.flip()
    clock.tick(30)

pygame.quit()

您还可以将代码放入intro_event_handle()intro_change()intro_draw()等函数中,以使其更具可读性。

import pygame


def intro_handle_event(event):
    global state

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_ESCAPE:                    
            state = 'GAME'
            reset_all_values() # 
        # other keys for intro

def game_handle_event(event):
    global state

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_ESCAPE: 
            state = 'GAMEOVER'
        # other keys for game

def gameover_handle_event(event):
    global state

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_ESCAPE: 
            state = 'INTRO'
        # other keys for gameover

def intro_change():
    pass

def game_change():    
    global state
    global scoreA

    scoreA += 1
    if scoreA >= 100:
        state = 'GAMEOVER'

def gameover_change():
    pass

def intro_draw(screen):
    text = font.render('INTRO - Press ESC', True, (255,255,255))
    rect = text.get_rect(center=screen.get_rect().center)
    screen.blit(text, rect)

def game_draw(screen):
    text = font.render('GAME - Wait for SCORE 100', True, (255,255,255))
    rect = text.get_rect(center=screen.get_rect().center)
    screen.blit(text, rect)
    text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
    rect = text.get_rect()
    screen.blit(text, rect)

def gameover_draw(screen):
    text = font.render('GAMEOVER - Press ESC', True, (255,255,255))
    rect = text.get_rect(center=screen.get_rect().center)
    screen.blit(text, rect)
    text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
    rect = text.get_rect()
    screen.blit(text, rect)

def reset_all_values():
    global scoreA
    global scoreB

    scoreA = 0
    scoreB = 0

    # reset other values

# --- main ---

size = (700, 500)

pygame.init()
screen = pygame.display.set_mode(size)

clock = pygame.time.Clock()

font = pygame.font.Font(None, 50)

reset_all_values()

# -------- Main Program Loop -----------

state = 'INTRO'

carry_on = True

while carry_on:

    # --- events ---

    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            carryOn = False 
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_x: 
                carry_on = False

        if state == 'INTRO':
            intro_handle_event(event)
        elif state == 'GAME':
            game_handle_event(event)
        elif state == 'GAMEOVER':
            gameover_handle_event(event)

    # --- changes/moves/collisions ---

    if state == 'INTRO':
        intro_change()
    elif state == 'GAME':
        game_change()
    elif state == 'GAMEOVER':
        gameover_change()

    # --- draws ---

    screen.fill((0,0,0))

    if state == 'INTRO':
        intro_draw(screen)
    elif state == 'GAME':
        game_draw(screen)
    elif state == 'GAMEOVER':
        gameover_draw(screen)

    pygame.display.flip()
    clock.tick(30)

pygame.quit()

您可以将函数保存在字典中

handle_event = {
   'INTRO': intro_handle_event,
   'GAME': game_handle_event,
   'GAMEOVER': gameover_handle_event,
}

并仅使用state (而不是if/elif )来执行正确的 function。

handle_event[state](event) 

import pygame


def intro_handle_event(event):
    global state

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_ESCAPE:                    
            state = 'GAME'
            reset_all_values() # 
        # other keys for intro

def game_handle_event(event):
    global state

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_ESCAPE: 
            state = 'GAMEOVER'
        # other keys for game

def gameover_handle_event(event):
    global state

    if event.type == pygame.KEYDOWN:
        if event.key == pygame.K_ESCAPE: 
            state = 'INTRO'
        # other keys for gameover

def intro_change():
    pass

def game_change():    
    global state
    global scoreA

    scoreA += 1
    if scoreA >= 100:
        state = 'GAMEOVER'

def gameover_change():
    pass

def intro_draw(screen):
    text = font.render('INTRO - Press ESC', True, (255,255,255))
    rect = text.get_rect(center=screen.get_rect().center)
    screen.blit(text, rect)

def game_draw(screen):
    text = font.render('GAME - Wait for SCORE 100', True, (255,255,255))
    rect = text.get_rect(center=screen.get_rect().center)
    screen.blit(text, rect)
    text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
    rect = text.get_rect()
    screen.blit(text, rect)

def gameover_draw(screen):
    text = font.render('GAMEOVER - Press ESC', True, (255,255,255))
    rect = text.get_rect(center=screen.get_rect().center)
    screen.blit(text, rect)
    text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
    rect = text.get_rect()
    screen.blit(text, rect)

def reset_all_values():
    global scoreA
    global scoreB

    scoreA = 0
    scoreB = 0

    # reset other values

# --- main ---

size = (700, 500)

pygame.init()
screen = pygame.display.set_mode(size)

clock = pygame.time.Clock()

font = pygame.font.Font(None, 50)

reset_all_values()

handle_event = {
   'INTRO': intro_handle_event,
   'GAME': game_handle_event,
   'GAMEOVER': gameover_handle_event,
}

change = {
   'INTRO': intro_change,
   'GAME': game_change,
   'GAMEOVER': gameover_change,
}

draw = {
   'INTRO': intro_draw,
   'GAME': game_draw,
   'GAMEOVER': gameover_draw,
}

# -------- Main Program Loop -----------

state = 'INTRO'

carry_on = True

    while carry_on:

        # --- events ---

        for event in pygame.event.get(): 
            if event.type == pygame.QUIT: 
                carryOn = False 
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_x: 
                    carry_on = False

            handle_event[state](event)

        # --- changes/moves/collisions ---

        change[state]()

        # --- draws ---

        screen.fill((0,0,0))

        draw[state](screen)

        pygame.display.flip()
        clock.tick(30)

    pygame.quit()

In similar way you can keep it in classes.

import pygame

class Intro():

    def __inti__(self):
        self.reset()

    def reset(self):
        pass

    def handle_event(self, event):
        global state

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:                    
                state = 'GAME'
                scene[state].reset() 
            # other keys for intro

    def change(self):
        pass

    def draw(self, screen):
        text = font.render('INTRO - Press ESC', True, (255,255,255))
        rect = text.get_rect(center=screen.get_rect().center)
        screen.blit(text, rect)

class Game():

    def __inti__(self):
        self.reset()

    def reset(self):
        global scoreA
        global scoreB

        scoreA = 0
        scoreB = 0

        # reset other values

    def handle_event(self, event):
        global state

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE: 
                state = 'GAMEOVER'
                scene[state].reset()
            # other keys for game

    def change(self):    
        global state
        global scoreA

        scoreA += 1
        if scoreA >= 100:
            state = 'GAMEOVER'
            scene[state].reset()

    def draw(self, screen):
        text = font.render('GAME - Wait for SCORE 100', True, (255,255,255))
        rect = text.get_rect(center=screen.get_rect().center)
        screen.blit(text, rect)
        text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
        rect = text.get_rect()
        screen.blit(text, rect)


class GameOver():

    def __inti__(self):
        self.reset()

    def reset(self):
        pass

    def handle_event(self, event):
        global state

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE: 
                state = 'INTRO'
                scene[state].reset()
            # other keys for gameover

    def change(self):
        pass

    def draw(self, screen):
        text = font.render('GAMEOVER - Press ESC', True, (255,255,255))
        rect = text.get_rect(center=screen.get_rect().center)
        screen.blit(text, rect)
        text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
        rect = text.get_rect()
        screen.blit(text, rect)

# --- main ---

size = (700, 500)

pygame.init()
screen = pygame.display.set_mode(size)

clock = pygame.time.Clock()

font = pygame.font.Font(None, 50)

scene = {
   'INTRO': Intro(),
   'GAME': Game(),
   'GAMEOVER': GameOver(),
}

# -------- Main Program Loop -----------

state = 'INTRO'

carry_on = True

while carry_on:

    # --- events ---

    for event in pygame.event.get(): 
        if event.type == pygame.QUIT: 
            carryOn = False 
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_x: 
                carry_on = False

        scene[state].handle_event(event)

    # --- changes/moves/collisions ---

    scene[state].change()

    # --- draws ---

    screen.fill((0,0,0))

    scene[state].draw(screen)

    pygame.display.flip()
    clock.tick(30)

pygame.quit()

这样您就可以构建有限的 State 机器


其他方法可以为每个状态创建单独的循环并将其放入将运行选定循环或退出游戏的外部循环。

import pygame

def intro_loop(screen):

    print('start intro loop')

    carry_on = True
    next_state = None

    while carry_on and not next_state:

        # --- events ---

        for event in pygame.event.get(): 
            if event.type == pygame.QUIT: 
                carry_on = False 
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_x: 
                    carry_on = False

                if event.key == pygame.K_ESCAPE:                    
                    next_state = 'GAME'

        # --- changes/moves/collisions ---


        # --- draws ---

        screen.fill((0,0,0))

        text = font.render('INTRO - Press ESC', True, (255,255,255))
        rect = text.get_rect(center=screen.get_rect().center)
        screen.blit(text, rect)

        pygame.display.flip()
        clock.tick(30)

    return carry_on, next_state 

def game_loop(screen):
    global scoreA
    global scoreB

    scoreA = 0
    scoreB = 0

    # reset other values

    print('start game loop')

    carry_on = True
    next_state = None

    while carry_on and not next_state:

        # --- events ---

        for event in pygame.event.get(): 
            if event.type == pygame.QUIT: 
                carry_on = False 
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_x: 
                    carry_on = False

                if event.key == pygame.K_ESCAPE: 
                    next_state = 'GAMEOVER'

        # --- changes/moves/collisions ---

        scoreA += 1
        if scoreA >= 100:
            next_state = 'GAMEOVER'

        # --- draws ---

        screen.fill((0,0,0))

        text = font.render('GAME - Wait for SCORE 100', True, (255,255,255))
        rect = text.get_rect(center=screen.get_rect().center)
        screen.blit(text, rect)
        text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
        rect = text.get_rect()
        screen.blit(text, rect)

        pygame.display.flip()
        clock.tick(30)

    return carry_on, next_state 

def gameover_loop(screen):

    print('start gameover loop')

    carry_on = True
    next_state = None

    while carry_on and not next_state:

        # --- events ---

        for event in pygame.event.get(): 
            if event.type == pygame.QUIT: 
                carry_on = False 
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_x: 
                    carry_on = False

                if event.key == pygame.K_ESCAPE:                    
                    next_state = 'INTRO'

        # --- changes/moves/collisions ---


        # --- draws ---

        screen.fill((0,0,0))

        text = font.render('GAMEOVER - Press ESC', True, (255,255,255))
        rect = text.get_rect(center=screen.get_rect().center)
        screen.blit(text, rect)
        text = font.render(f'SCORE {scoreA}' , True, (255,255,255))
        rect = text.get_rect()
        screen.blit(text, rect)

        pygame.display.flip()
        clock.tick(30)

    return carry_on, next_state 

# --- main ---

size = (700, 500)

pygame.init()
screen = pygame.display.set_mode(size)

clock = pygame.time.Clock()

font = pygame.font.Font(None, 50)

# -------- Main Program Loop -----------

state = 'INTRO'
carry_on = True

while carry_on:

    if state == 'INTRO':
        carry_on, state = intro_loop(screen)
    elif state == 'GAME':
        carry_on, state = game_loop(screen)
    elif state == 'GAMEOVER':
        carry_on, state = gameover_loop(screen)

pygame.quit()

我假设从您的表述方式来看,您的问题是游戏的重新运行,而不是提出问题的游戏结束屏幕。 假设是这种情况...

我不同意尝试将不同状态组合成一个游戏循环的方法。 当然可以,但在这种情况下没有真正好的理由这样做。 它使代码更难遵循,而不会从这种结构中获得任何好处。 在某些情况下,state 机器方法是有意义的,但这确实不是其中之一。

添加一个包含有关重新启动游戏的问题的额外循环可以比这简单得多。

carryOn = True

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

除了这一行:

clock = pygame.time.Clock()

并将所有这些移到一个名为run_game()的方法中

您还需要移动初始化桨和球位置的线,以及user_lose = False并将其移动到run_game()方法的开头。

然后,当您想运行游戏时,您可以调用它。 退出后,您可以询问他们是否要再次播放,如果他们愿意,请再次调用它,如果他们选择不这样做,则退出。 当然,您需要在一个循环中多次重复此操作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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