如何在按下键盘按钮之间添加延迟?

How can I add a delay between keyboard button presses?

我想在我的游戏中添加一个“射击”功能,玩家 - 无人机 - 会在按下键盘上的 space 栏时发射子弹。

我已经成功完成了,但我还希望函数在执行一次后延迟。例如,玩家可以按一次 spacebar 然后必须等待 2-3 秒才能再次执行该功能。因此我的问题是,我怎样才能做到这一点?

这是当前的功能代码。

main.py

    def shoot(self):
        self.get_drone_coordinates()

        x = self.drone_coordinates[0][0]
        y = self.drone_coordinates[0][1] - 20

        self.drone_bullet = Image(source="images/drone_bullet.png",
                                  pos=(x, y))

        self.add_widget(self.drone_bullet)
        self.bullets.append(self.drone_bullet)

controls.py

def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
    elif keycode[1] == 'spacebar':
        self.shoot()

我尝试导入时间库并在 controls.py 中的函数中添加一个 time.sleep() 函数,但这会冻结整个程序。

import time

def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
    elif keycode[1] == 'spacebar':
        self.shoot()
        time.sleep(3)

如有任何帮助,我们将不胜感激!提前致谢!

试试这个:

import time
def _on_keyboard_down(self, keyboard, keycode, text, modifiers,cooldown==3):
  elif keycode[1] == 'spacebar':
      try:
            LastShot
      except:
            LastShot=0
      if time.time()-LastShot>=cooldown:
            self.shoot()
            LastShot=time.time()

基本上就是检查上次射击到现在的时间是否大于等于冷却时间,然后记录上次射击的时间。

time.time() 不休眠,所以它不会停止您的程序。这确保您的程序保持 运行,即使在等待冷却完成时也是如此。

kivy中异步事件的最佳选择是使用asyncio。首先,您必须确保您的应用 运行 来自 asyncio.run() 而不是 App.run()。为此,您必须导入 asyncio,还必须向您的 App class 添加一个方法。请参阅以下示例:

import asyncio

######## MAIN APP ######## 
class ExampleApp(App):
    def build(self):
        #Your  app stuff here

    async def kivyCoro(self):  #This is the method that's gonna launch your kivy app
        await self.async_run(async_lib='asyncio')
        print('Kivy async app finished...')

    # This func will start all the "tasks", in this case the only task is the kivy app
    async def base(self):
        (done, pending) = await asyncio.wait({self.kivyCoro()}, 
    return_when='FIRST_COMPLETED')

if __name__ == '__main__':
    instanceApp = ExampleApp() #You have to instanciate your App class
    asyncio.run(instanciaApp.base()) # Run in async mode

上面的代码将使您的 kivyApp 成为 运行 作为“任务”(任务是将要同时执行的东西)。一个任务或协程可以在其自身内部调用另一个任务,所以你可以在你的 kivyApp 执行期间有另一个异步任务 运行ning。

# Here you create a coroutine (global scope)
async def delayWithoutFreeze():
    print('Wait 3 segs...')
    await asyncio.sleep(3)
    print('3 segs elapsed...')

最后,您只需将该异步函数作为任务调用,即可从您的 _on_keyboard_down 函数中执行此操作:

def _on_keyboard_down(self, keyboard, keycode, text, modifiers):
    j = 0 #This is a counter to know if a delay task is running
    elif keycode[1] == 'spacebar':
        for task in asyncio.all_tasks(): #This loop checks if there's a delay already running
            if task.get_name()=='shootTask':
                j+=1
                print('Theres already {} shootTask'.format(j))
        if j==0: #If j == 0 means that no delay is running so you can press and action again
            # This is how you call the async func
            asyncio.create_task(delayWithoutFreeze(), name='shootTask') 
            self.shoot()
        

注意:不知道你为什么在 _on_keyboard_down 中使用 elif 而不是 if。你只有1个条件。不需要 elif

有关协程和任务的更多信息: https://docs.python.org/3/library/asyncio-task.html