如何检查键盘按钮是不是收到垃圾邮件并在再次按下之前添加冷却时间

Posted

技术标签:

【中文标题】如何检查键盘按钮是不是收到垃圾邮件并在再次按下之前添加冷却时间【英文标题】:How to check if keyboard button is getting spammed and add a cool down on before it can be pressed again如何检查键盘按钮是否收到垃圾邮件并在再次按下之前添加冷却时间 【发布时间】:2019-10-30 03:08:11 【问题描述】:

我想知道如何为按下的特定按键添加计时器/冷却时间。例如,用户正在向攻击键(在我的情况下为 p)发送垃圾邮件,我想在该人无法向此按钮发送垃圾邮件的地方(在空中和地面)添加一个冷却时间。 这是问题所在: https://drive.google.com/file/d/1XH-u-1qm2I0ftlCLPSsPMjTJjJGQdsUp/view?usp=sharing

正如您在视频中看到的那样,此人可以无限期地向攻击按钮发送垃圾邮件并消除游戏的目的。

我尝试过设置睡眠定时器,例如 def 睡眠者(): 如果输入()==“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 秒。

【问题讨论】:

【参考方案1】:

当某个键被按下时,您必须存储允许再次“按下”该键的时间。 为此使用字典:

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() 的结果存储到一个变量中并改用该变量。例如:

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]:
    # [...]

【讨论】:

我似乎无法正确实现它:paste.pythondiscord.com/axotoxijub.py 我尝试移动语句 aronund 但它不起作用。用新东西更新了完整的 pygame 代码:paste.pythondiscord.com/jafutoneku.py @WajdanFaheem getPressed 是全局范围内的函数。当您使用它时,您只需将keys[pygame.k_p] 替换为getPressed(keys, pygame.k_p, 2000) 或将结果存储到变量中。阅读我现在添加的答案的最后一部分。 由于某种原因,它没有播放动画,也没有启动冷却。只是为了确定(对不起,如果我听起来很需要),对于 x 次点击,在 y 时间内,z 将是等待时间,直到它可以再次按下。这就是问题的对象。这是实现:link。此外,只是 pygame.k_p 不起作用,所以我需要添加 keys()【参考方案2】:

您要查找的术语称为“去抖动”。正如您所发现的,消除用户输入的抖动通常很有用,以确保不会过于频繁地按下单个按钮,或者不会将单次长按计为多次按下。

在任何情况下,为了消除用户输入的抖动,您必须跟踪最后一次按下按钮的时间,并且只有在经过足够长的时间后才能再次按下该按钮。这样的事情应该可以工作:

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()

你不想睡觉是对的,因为睡觉会阻碍游戏的其余部分取得进展。相反,在经过一定时间之前忽略未来的压力。

【讨论】:

我认为我没有正确实施它,因为它并没有真正做任何事情我想知道您是否可以帮助我?这是更新代码的链接:link do_the_thing() 还有什么作用?我确实有这个功能还是一般性陈述 对不起,do_the_thing() 只是一个占位符,用于在按下按钮时实际想要执行的任何逻辑。

以上是关于如何检查键盘按钮是不是收到垃圾邮件并在再次按下之前添加冷却时间的主要内容,如果未能解决你的问题,请参考以下文章

在 Native Base 上打开键盘时如何避免双击?

如果用户在返回键盘之前按下按钮,如何将按钮操作应用于文本字段

在按下 Arduino 上的特定键盘按钮之前,如何让步进电机运行?

我们如何检测用户是不是使用 MessageKit 按下键盘上的“发送/返回”按钮?

按下按钮后如何使“提交”表单从 Ajax 工作

按下回车键隐藏 android 键盘