Как проверить, не спам ли кнопка на клавиатуре и добавить охлаждение, прежде чем ее можно будет снова нажать - PullRequest
2 голосов
/ 16 июня 2019

Я хочу знать, как добавить таймер / режим охлаждения к определенной нажатой кнопке. Например, пользователь спамит ключ атаки (в моем случае p), и я хочу добавить время восстановления, когда человек не может спамить эту кнопку (в воздухе и на земле). Вот проблема: https://drive.google.com/file/d/1XH-u-1qm2I0ftlCLPSsPMjTJjJGQdsUp/view?usp=sharing

Как вы можете видеть на видео, человек может спамить кнопку атаки бесконечно и удаляет цель игры.

Я попытался установить таймер сна, такой как def Sleeper (): if input () == "p": с (20) но я не думаю, что это то, как вы это делаете. Кроме этого я не знаю других способов попробовать.

Ссылка на весь мой код: https://hastebin.com/zujanifisu.py

Более конкретный код:

def movement(self, window):
        pygame.time.delay(20)
        if self.runcount >= 3:
            self.runcount = 0

        if self.running == True:
            window.blit(run[self.runcount],(int(self.player_x),int(self.player_y)))
            self.runcount +=1
            self.hitbox_running = pygame.Rect(self.player_x+30,self.player_y+20,48,70)
            pygame.draw.rect(window,(255,0,0),self.hitbox_running, 2)

        if (keys[pygame.K_DOWN]) or ((keys[pygame.K_DOWN]) and keys[pygame.K_p]):
            if self.player_y == 378:
                self.running = False
                if self.slidecount >= 4:
                    self.slidecount = 0

                if self.sliding:  
                    window.blit(slide[self.slidecount],(int(self.player_x),int(self.player_y)))
                    self.slidecount +=1
                    pygame.draw.rect(window,(255,0,0),self.hitbox_sliding, 2)

        if event.type == pygame.KEYDOWN:
            if (event.key == pygame.K_DOWN )and self.player_y < self.width:

                self.running = False
                self.jumping = False
                self.fallspeed += 0.2

                if self.fallingcount >= 1:
                    self.fallingcount = 0
                if self.fall:
                    window.blit(falling[self.fallingcount], (int(self.player_x),int(self.player_y)))
                    self.hitbox_falling = pygame.Rect(self.player_x+30,self.player_y,35,80)
                    pygame.draw.rect(window,(255,0,0),self.hitbox_falling, 2)                    
                    self.fallingcount +=1
        if keys[pygame.K_UP] and keys[pygame.K_p] :
            self.fallspeed = 0.3
            self.running = False
            self.jumping = False
            self.sliding = False
            if self.attackcount >= 16:
                self.attackcount = 0
            if self.attacking: 
                window.blit(attack[self.attackcount],(int(self.player_x),int(self.player_y)))
                self.attackcount += 1
                self.hitbox_attacking = pygame.Rect(self.player_x+30,self.player_y+20,38,70)
                self.hitbox_sword = pygame.Rect(self.player_x+72, self.player_y+20, 20, 50)
                pygame.draw.rect(window,(255,0,0),self.hitbox_attacking, 2)
                pygame.draw.rect(window,(255,0,0),self.hitbox_sword, 2)
            if self.jumpingcount >= 20:
                self.jumpingcount = 0
            if self.jumping and self.player_y < self.width:  
                window.blit(jump[self.jumpingcount],(int(self.player_x),int(self.player_y)))
                self.hitbox_jumping = pygame.Rect((self.player_x+20),(self.player_y+20),52,55)
                pygame.draw.rect(window,(255,0,0),self.hitbox_jumping, 2)
                self.jumpingcount +=1
                self.fallspeed = 0.3

        if keys[pygame.K_UP]:
            self.fallspeed = 0.3
            self.running = False
            if self.jumpingcount >= 20:
                self.jumpingcount = 0

            if self.jumping and self.player_y < self.width:  
                window.blit(jump[self.jumpingcount],(int(self.player_x),int(self.player_y)))
                self.hitbox_jumping = pygame.Rect((self.player_x+20),(self.player_y+20),52,55)
                pygame.draw.rect(window,(255,0,0),self.hitbox_jumping, 2)
                self.jumpingcount +=1
                self.fallspeed = 0.3

        if keys[pygame.K_p] and not keys[pygame.K_UP]:
            self.running = False
            self.jumping = False
            self.sliding = False
            if self.attackcount >= 16:
                self.attackcount = 0

            if self.attacking:
                self.hitbox_attacking = pygame.Rect(self.player_x+30,self.player_y+20,38,70)
                self.hitbox_sword = pygame.Rect(self.player_x+72, self.player_y+20, 20, 50)
                window.blit(attack[self.attackcount],(int(self.player_x),int(self.player_y)))
                self.attackcount += 1
                pygame.draw.rect(window,(255,0,0),self.hitbox_attacking, 2)
                pygame.draw.rect(window,(255,0,0),self.hitbox_sword, 2)
        if keys[pygame.K_DOWN] and keys[pygame.K_UP]:
            self.running = False


        if event.type == pygame.KEYUP:
            if event.key == pygame.K_DOWN:
                self.running = True
                self.jumping = True
                self.fallspeed = 0.3

            if event.key == pygame.K_UP:
                self.running=True
            if event.key == pygame.K_p:
                self.running = True
                self.jumping = True
                self.sliding = True

Большая часть проблемы связана с ключами [pygame.k_p]

Я хочу добавить таймер к общей кнопке p, поэтому при нажатии 2-3 раза ее нельзя нажимать еще 2-3 секунды.

Ответы [ 2 ]

2 голосов
/ 16 июня 2019

Когда клавиша была нажата, вам нужно сохранить время, когда клавише разрешено повторное нажатие.
Используйте словарь для этого:

key_timeout = {}

Напишите функцию в глобальной области видимости, которая проверяет, нажата ли клавиша и разрешено ли ее нажатие. Параметрами функции являются состояние клавиш (pygame.key.get_pressed()), ключ и время ожидания в миллисекундах:

def getPressed(keys, key, timeout):

Если клавиша не нажата, функция возвращает False:

if keys[key] == False:
    return False

Используйте pygame.time.get_ticks(), чтобы получить время в миллисекундах:

current_time = pygame.time.get_ticks()

Если в словаре хранится тайм-аут и время меньше, чем время повторного нажатия клавиши, функция возвращает False:

if key in key_timeout and key_timeout[key] > current_time:
   return Fase

Добавьте время ожидания к текущему времени, это время, когда клавише разрешено повторное нажатие, и сохраните ее в словаре.

 key_timeout[key] = current_time + timeout

Полный код функции:

key_timeout = {}
def getPressed(keys, key, timeout):
    global key_timeout

    if keys[key] == False:
        return False

    current_time = pygame.time.get_ticks()

    if key in key_timeout and key_timeout[key] > current_time:
        return False

    key_timeout[key] = current_time + timeout
    return True

Вместо if keys[pygame.k_p]: вы можете позвонить:

if getPressed(keys, pygame.k_p, 2000): # 2000 milliseconds == 2 seconds
    # [...]

Если вы запрашиваете состояние ключа (например, keys[pygame.k_p]) несколько раз в функции, то вам нужно сохранить результат getPressed() в переменной и использовать ее вместо этого. e.g.:

key_p_pressed = getPressed(keys, pygame.k_p, 2000)

if (keys[pygame.K_DOWN]) or ((keys[pygame.K_DOWN]) and key_p_pressed ):
    # [...]

if keys[pygame.K_UP] and key_p_pressed:
    # [...]

if key_p_pressed and not keys[pygame.K_UP]:
    # [...]
0 голосов
/ 16 июня 2019

Термин, который вы ищете, называется "debouncing".Как вы обнаружили, часто бывает полезно отменить ввод данных пользователем, чтобы убедиться, что одна кнопка не нажимается слишком часто, или чтобы одно длительное нажатие не считалось несколькими нажатиями.

В любом случаеДля того, чтобы отменить ввод пользователя, вы должны отслеживать, когда кнопка была нажата в последний раз, и сделать ее пригодной для повторного нажатия только по прошествии достаточного времени.Примерно так должно работать:

buttons_last_pressed = {}
...
now = time.time()
if is_pressed[BUTTON]:
    last_pressed = buttons_last_pressed.get(BUTTON)
    if (last_pressed is None) or (now - last_pressed >= threshold):
        buttons_last_pressed[BUTTON] = now
        do_the_thing()

Вы правы, что не хотите спать, потому что сон мешает остальной части игры прогрессировать.Вместо этого просто игнорируйте будущие нажатия, пока не пройдет определенное время.

...