How can I add a delay between keyboard button presses?
The best choice for async events in kivy is to use asyncio
. First at all you have to be sure your app runs from asyncio.run()
instead of App.run()
. To do this, you have to import asyncio and also you have to add a method to your App class. See the example below:
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
The code above will make your kivyApp to run as a "Task" (a task it's something that's gonna be concurrently executed). A task or coroutine can call another task within itself, so you can have another async task running during the execution of your kivyApp.
# Here you create a coroutine (global scope)
async def delayWithoutFreeze():
print('Wait 3 segs...')
await asyncio.sleep(3)
print('3 segs elapsed...')
Finally you just have to call that async function as a task, to do that from your _on_keyboard_down
function:
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()
NOTE: Idk why u use elif
instead if
in the _on_keyboard_down
. You only have 1 condition. no elif
needed
For more info about coroutines and tasks: https://docs.python.org/3/library/asyncio-task.html
Try this:
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()
Basically, it checks whether the time between the last shot and now is greater or equal to the cooldown, then records the time of the last shot.
time.time()
doesn't sleep, so it doesn't stop your program. This makes sure that your program keeps running, even when waiting for the cooldown to finish.