如何在按下键盘按钮之间添加延迟?
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
我想在我的游戏中添加一个“射击”功能,玩家 - 无人机 - 会在按下键盘上的 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