如何让一个动作在 Python / Pygame 中只发生一次

How To Make An Action Happen Only Once In Python / Pygame

我正在 Python / Pygame 编写游戏代码。目前我正在研究玩家的移动,但我已经意识到,如果我按住 space 条(即激活我的跳跃移动的按钮),它会一直上升并且永远不会下降。我已经实现了重力,但它只在我按下按钮一次时发生。我希望这样我只能跳一次而且我的角色不会一直飞。 这是我的代码(请帮忙!)

# This is my player file
import pygame

class Player(pygame.sprite.Sprite):
    def __init__(self, pos):
        super().__init__()
        self.image = pygame.Surface((32,64))
        self.image.fill('red')
        self.rect = self.image.get_rect(topleft = pos)

    # Player Movement

    self.direction = pygame.math.Vector2(0, 0)
    self.speed = 7
    self.gravity = 0.7
    self.jump_speed = -14

    # player status
    self.status = 'idle'
    self.facing_right = True
    self.on_ground = False
    self.on_ceiling = False
    self.on_left = False
    self.on_right = False

# Key Pressed

def get_input(self):
    keys = pygame.key.get_pressed()

    if keys[pygame.K_RIGHT]:
        self.direction.x = 1
    elif keys[pygame.K_LEFT]:
        self.direction.x = -1
    else:
        self.direction.x = 0

    if keys[pygame.K_SPACE]:
        self.jump() 
    

# Gravity       

def apply_gravity(self):
        self.direction.y += self.gravity
        self.rect.y += self.direction.y 

# Jumping

def jump(self):
    self.direction.y = self.jump_speed          

# Updating The Player       

def update(self):
    self.get_input()
    self.apply_gravity()

处理单个按键的最佳方法是使用 pygameevent 模块。在主游戏循环中使用 pygame.event.get()

这让你可以用单个 'events' 做一些事情,比如按下或释放一个键。

您可以通过添加一个 space_is_pressed 变量来解决此问题] 发布时)。然后只有在 keys[pygame.K_SPACE]True,但 space_is_pressedFalse。 我只建议你在无法实现 pygame.event.get() 方法时这样做。

首先为什么你不只允许在 self.on_ground 时跳转?

class Player(pygame.sprite.Sprite):
    # [...]

    def get_input(self):
        # [...]

        if keys[pygame.K_SPACE] and self.on_ground:
            self.jump() 

无论如何,你必须使用 KEYDOWN 事件而不是 pygame.key.get_pressed()

pygame.key.get_pressed() returns a list with the state of each key. If a key is held down, the state for the key is True, otherwise False. Use pygame.key.get_pressed() 评估按钮的当前状态并获得连续移动。

键盘事件(参见 pygame.event 模块)仅在键状态改变时发生一次。 KEYDOWN 事件在每次按下一个键时发生一次。 KEYUP 每松开一个键就会出现一次。使用键盘事件进行单个操作或逐步移动。

class Player(pygame.sprite.Sprite):
    # [...]

    def get_input(self):
    
        keys = pygame.key.get_pressed()
        if keys[pygame.K_RIGHT]:
            self.direction.x = 1
        elif keys[pygame.K_LEFT]:
            self.direction.x = -1
        else:
            self.direction.x = 0

        for event in event_list:
            if event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                self.jump() 
# application loop
while run:

    #event loop
    event_list = pgame.event.get()
    for event in event_list:
        if event.type == pygame.QUIT:
            run = False
  
    # [...]

注意,pygame.event.get() 获取所有消息并将它们从队列中删除。请参阅文档:

This will get all the messages and remove them from the queue. [...]

如果在多个事件循环中调用pygame.event.get(),则只有一个循环接收事件,而不是所有循环都接收所有事件。因此,有些事件似乎被遗漏了。


或者,您可以使用状态属性防止连续多次跳转:

class Player(pygame.sprite.Sprite):
    def __init__(self, pos):
        # [...]
        self.is_jumping = False

    def get_input(self):

        keys = pygame.key.get_pressed()
        if keys[pygame.K_RIGHT]:
            self.direction.x = 1
        elif keys[pygame.K_LEFT]:
            self.direction.x = -1
        else:
            self.direction.x = 0

        space_pressed = keys[pygame.K_SPACE]:
        if space_pressed and not self.is_jumping:
            self.jump() 
        self.is_jumping = space_pressed
       

只要按键被按下,事件'key pressed'就为真。而 'key down' 事件仅在键按下时发生。 这不是解决问题的方法吗?