【问题标题】:Pygame Pause Functionality [duplicate]Pygame暂停功能[重复]
【发布时间】:2021-07-18 04:01:00
【问题描述】:

我一直在尝试为我的乒乓球游戏添加暂停功能,但它不起作用。我可以暂停一次游戏然后它停止,但之后如果我按下暂停游戏的键,游戏将移动几帧然后停止。之后,我必须按住暂停按钮才能使游戏移动。我将链接下面的类代码:

class Game:
    def __init__(self, start):
        self.start = start
        self.score1 = 0
        self.score2 = 0
        self.pause = False
        self.over = False

    def play(self, ai):
        player2.AI = ai
        screen = pygame.display.set_mode(size)
        pygame.display.set_caption("Pong")
        self.over = False
        while self.start:
            # quits if x is pressed
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    exit()
            pressed_keys = pygame.key.get_pressed()
            if pressed_keys[pygame.K_p]:
                self.pauseMenu()
            if self.pause == False:
                # creates list of pressed keys and using that to determine movement
                pressed_keys = pygame.key.get_pressed()
                if pressed_keys[pygame.K_w]:
                    player1.moveUp(5)
                if pressed_keys[pygame.K_s]:
                    player1.moveDown(5)
                if player2.AI == True:
                    player2.AI_move(ball)
                if pressed_keys[pygame.K_SPACE]:
                    pygame.quit()
                else:
                    if pressed_keys[pygame.K_UP]:
                        player2.moveUp(5)
                    if pressed_keys[pygame.K_DOWN]:
                        player2.moveDown(5)

                if pressed_keys[pygame.K_p]:
                    self.pauseMenu()

                # scoring system if ball touches variable, increments score and resets ball to middle
                if ball.rect.x >= 790:
                    self.score1 += 1
                    ball.rect.x = 400
                    ball.rect.y = 240
                    ball.x_velo = choice([-2, 2])
                    ball.y_velo = choice([-1, -2, 1, 2])
                if ball.rect.x <= 0:
                    self.score2 += 1
                    ball.rect.x = 400
                    ball.rect.y = 240
                    ball.x_velo = choice([-2, 2])
                    ball.y_velo = choice([-1, -2, 1, 2])

                # bounces ball of top or bottom wall
                if ball.rect.y > 470 or ball.rect.y < 0:
                    ball.y_velo = -ball.y_velo

                # detects collision and reflects ball off board
                if pygame.sprite.collide_mask(ball, player1) or pygame.sprite.collide_mask(ball, player2):
                    ball.bounce()

                # refresh method to move ball
                ball.refresh()
                # draws background and sprites onto screen each tick
                screen.fill(BLACK)
                pygame.draw.line(screen, WHITE, [400, 0], [400, 580], 1)
                all_sprites_list.update()
                all_sprites_list.draw(screen)

                # draws score at top
                font = pygame.font.Font('ARCADECLASSIC.TTF', 74)
                text = font.render(str(self.score1), 1, BLUE)
                screen.blit(text, (300, 10))
                text = font.render(str(self.score2), 1, BLUE)
                screen.blit(text, (470, 10))
                if self.score1 >= 5:
                    self.victory("Player 1")
                elif self.score2 >= 5:
                    self.victory("Player 2")
                # refreshes display each tick
                pygame.display.flip()
                # sets number of ticks per second
                clock.tick(60)

    def victory(self, winner):
        pass

    def pauseMenu(self):
        if self.pause == True:
            self.pause = False
        elif self.pause == False:
            self.pause = True

【问题讨论】:

  • 最好使用event 而不是pressed_keys(),因为当您按下按钮时,它可以运行pressed_keys() 千次 - 所以pause 将切换到TrueFalse 千次旁边次 - 但它只会运行一个event。如果你在if pressed_keys[pygame.K_p]: 中添加print(),那么你会看到一千条消息而不是一条。
  • 你可以在单行切换暂停self.pause = not self.pause

标签: python class pygame pause


【解决方案1】:

你可以试试这个:

pause=False
#your game code
for event in pygame.event.get():
    if event.type==KEYUP:
            if event.key==K_p:
                pause = True

while pause == True:
        for event in pygame.event.get():
            if event.type==KEYUP:
                if event.key==K_p:
                    pause = False

#your remaining code

您首先将暂停设为 false,然后添加一个暂停屏幕的键。

【讨论】:

  • 在没有 pygame.event.get() 方法的情况下有没有办法做到这一点?
  • @Mason19Kelley 如果没有event,您将不得不记住pressed_keys[pygame.K_p] 的先前值并与pressed_keys[pygame.K_p] 的当前值进行比较-如果它从False 更改为True,那么您将必须更改pause。所以你必须用event 做你已经拥有的东西。只有在将值从 True 更改为 FalseKEYUP 将值从 False 更改为 True 时,您才会得到 event KEYDOWN
【解决方案2】:

问题是代码运行速度非常快,当您按下按钮 P 时,它会多次运行循环并检查 pressed_keys() 多次 - 所以它执行 pauseMenu() 很多次,它会更改 pause 很多次并且你不知道最后一个值是True 还是False。但是你只需要执行一次pauseMenu()

您可以为此使用event,因为当您按下按钮时,系统只会发送一个事件,并且它将运行pauseMenu() 只会运行。

        # quits if x is pressed
        for event in pygame.event.get():

            if event.type == pygame.QUIT:
                pygame.quit()
                exit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_p:
                    # toggle value 
                    self.pause = not self.pause

使用pressed_keys[pygame.K_p],您必须记住先前的值pressed_keys[pygame.K_p],并将其与当前值pressed_keys[pygame.K_p] 进行比较——如果它从False 更改为True,那么您将不得不更改pause。所以你必须做你已经拥有的事件。

# before loop

previus_key_p = False

# inside loop

pressed_keys = pygame.key.get_pressed()

if pressed_keys[pygame.K_p] and previus_key_p = False:
   self.pauseMenu()

previus_key_p = pressed_keys[pygame.K_p]

如果您在if self.pause == False: 之前选中按钮P,那么您不必在if self.pause == False: 内再次执行此操作

编辑:添加缺少的代码后,我运行代码,主要问题是第二个if self.pause == False:


顺便说一句:

要切换值True/False,您可以使用not

def pauseMenu(self):
    self.pause = not self.pause

顺便说一句:

pygame.mouse.get_button() 用于按下屏幕上的按钮时,我很少看到类似的问题,然后在同一个地方显示新按钮 - 它立即按下新按钮。


编辑:

最少的工作代码。

它需要移动球员的功能,但球在移动,你可以暂停它。它还可以在暂停时显示文本 - 我在 if not self.pause: 之外绘制所有内容并在 Pause 绘制文本,但在暂停时我什至可以绘制一些动画。

我还将ball.refresh() 重命名为ball.update(),并将ball 添加到组中,现在组对所有对象运行update()

我添加了前缀为# &lt;---的cmets

import pygame
from random import choice

# --- constants --- (PEP8: UPPER_CASE_NAMES)

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED   = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE  = (0, 0, 255)

# --- classes --- (PEP8: CamelCaseNames)

class Game:

    def __init__(self, start):
        self.start = start
        self.score1 = 0
        self.score2 = 0
        self.pause = False
        self.over = False

    def play(self, ai):
        player2.AI = ai
        screen = pygame.display.set_mode(size)
        pygame.display.set_caption("Pong")
        self.over = False

        # <--- you can create it once
        #font = pygame.font.Font('ARCADECLASSIC.TTF', 74)
        font = pygame.font.SysFont(None, 74)
        
        # <--- value at start
        previous_key_p = False
        
        while self.start:
            # quits if x is pressed
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    exit()

            pressed_keys = pygame.key.get_pressed()
            
            # <--- check also previous value
            if pressed_keys[pygame.K_p] and previous_key_p == False:
                self.pauseMenu()

            # <--- keep current value to check it in next loop
            previous_key_p = pressed_keys[pygame.K_p]

            if not self.pause:
                # creates list of pressed keys and using that to determine movement
                pressed_keys = pygame.key.get_pressed()
                if pressed_keys[pygame.K_w]:
                    player1.moveUp(5)
                if pressed_keys[pygame.K_s]:
                    player1.moveDown(5)
                if player2.AI == True:
                    player2.AI_move(ball)
                if pressed_keys[pygame.K_SPACE]:
                    pygame.quit()
                else:
                    if pressed_keys[pygame.K_UP]:
                        player2.moveUp(5)
                    if pressed_keys[pygame.K_DOWN]:
                        player2.moveDown(5)

                # <--- you don't need it 
                #if pressed_keys[pygame.K_p]:
                #    self.pauseMenu()

                # scoring system if ball touches variable, increments score and resets ball to middle
                if ball.rect.x >= 790:
                    self.score1 += 1
                    ball.rect.x = 400
                    ball.rect.y = 240
                    ball.x_velo = choice([-2, 2])
                    ball.y_velo = choice([-1, -2, 1, 2])
                if ball.rect.x <= 0:
                    self.score2 += 1
                    ball.rect.x = 400
                    ball.rect.y = 240
                    ball.x_velo = choice([-2, 2])
                    ball.y_velo = choice([-1, -2, 1, 2])

                # bounces ball of top or bottom wall
                if ball.rect.y > 470 or ball.rect.y < 0:
                    ball.y_velo = -ball.y_velo

                # detects collision and reflects ball off board
                if pygame.sprite.collide_mask(ball, player1) or pygame.sprite.collide_mask(ball, player2):
                    ball.bounce()

                # <--- I renamed it to `update()` and add to group so I don't have to run it manually
                # refresh method to move ball
                #ball.update()

                all_sprites_list.update()

                if self.score1 >= 5:
                    self.victory("Player 1")
                elif self.score2 >= 5:
                    self.victory("Player 2")
    
            # <-- outside `pause` - so it can display animation also when paused
                            
            # --- only draws (without updates, etc.) --- 
            
            # draws background and sprites onto screen each tick
            screen.fill(BLACK)
            
            pygame.draw.line(screen, WHITE, [400, 0], [400, 580], 1)
            
            all_sprites_list.draw(screen)

            # draws score at top
            text1 = font.render(str(self.score1), 1, BLUE)
            screen.blit(text1, (300, 10))
            
            text2 = font.render(str(self.score2), 1, BLUE)
            screen.blit(text2, (470, 10))

            if self.pause:
                text = font.render('PAUSE', 1, RED)
                rect = text.get_rect()
                rect.center = screen.get_rect().center
                screen.blit(text, rect)
            
            # refreshes display each tick
            pygame.display.flip()
            
            # sets number of ticks per second
            clock.tick(60)

    def victory(self, winner):
        pass

    def pauseMenu(self):
        if self.pause == True:
            self.pause = False
        elif self.pause == False:
            self.pause = True

class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.surface.Surface((10,100))
        self.image.fill(GREEN)
        self.rect = self.image.get_rect()
        self.mask =  pygame.mask.from_surface(self.image)

class Ball(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.surface.Surface((10,10))
        self.image.fill(RED)
        self.rect = self.image.get_rect()
        self.mask =  pygame.mask.from_surface(self.image)
        
    # <--- I renamed `refresh` to `update()`         
    def update(self):        
        self.rect.x += 1
        
    def bounce(self):        
        pass

# --- functions --- (PEP8: lower_case_names)

# ... empty ...

# --- main ---
        
size = (800, 600)    

pygame.init()

player1 = Player()
player2 = Player()
ball = Ball()

all_sprites_list = pygame.sprite.Group((player1, player2, ball))

clock = pygame.time.Clock()
Game(True).play(False)

【讨论】:

  • 我添加了最少的工作代码。
  • 非常感谢!我已经为此苦苦挣扎了几天,并且阻碍了我的项目!我不想使用事件方法的原因是因为我正在使用 RPi 为我的新生项目制作街机,最终输入将是一个按钮,所以我可以轻松地将 press_keys 输入与按钮输入交换。再次感谢。
  • 如果您的意思是附加到 RPI gpio 的按钮,那么我认为您无法使用 pressed_keys() 捕获它。相反,您必须为此使用模块gpio。也许它可以类似于events :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-19
  • 1970-01-01
  • 2020-08-24
  • 2017-01-08
  • 2014-02-07
  • 1970-01-01
相关资源
最近更新 更多