2016-12-05 101 views
0

我正在尝试使用python asyncio制作一个准系统骨架格斗游戏。Python asyncio:可中断任务

class Skeleton(Creature): 
    pass 

class SkeletonAI(): 
    def __init__(self, skeleton,loop = None): 
     self.loop = loop or asyncio.new_event_loop() 
     self.skeleton = skeleton 
     self.action_task = None 


    async def run(self): 
     while True: 
      #print(self.action_task,) 
      if self.skeleton.alive and self.skeleton.target.alive: 
       if self.skeleton.state == 'idle': 
        #ATTACK 
        self.skeleton.begin_attack() 
        self.action_task = self.loop.call_later(3, self.skeleton.action_complete) 

      else: 
       break 


class Player(Creature): 
    def attack_target(self, target): 
     target.take_damage(self.damage) 
     if target.state == 'attacking': 
      target.state = 'idle' 
      #interrupt attack 

class Game(): 

    #Super simple game 

    #The skeleton launches an attack, press anything to interrupt it 
    async def handle_sending(self): 
     loop = asyncio.get_event_loop() 
     executor = concurrent.futures.ThreadPoolExecutor(
      max_workers=1, 
     ) 
     while True: 
      msg = await loop.run_in_executor(executor, input) 
      print('got a message') 
      if self.skeleton_ai.action_task: 
       print('cancelling attack') 
       self.skeleton_ai.action_task.cancel() 
       self.skeleton_ai.skeleton.machine.set_state('idle') 

       print('cancelled attack') 
       self.skeleton_ai.action_task = None 

    async def game_loop(self): 
     player_task = asyncio.ensure_future(self.handle_sending()) 
     skeleton_task = asyncio.ensure_future(self.skeleton_ai.run()) 
    def __init__(self): 
     self.task = None 
     self.loop = asyncio.get_event_loop() 
     self.player = Player(name='ply') 
     self.skeleton_ai = SkeletonAI(skeleton=Skeleton(name='bobby')) 
     self.skeleton_ai.skeleton.target = self.player 
     self.loop.run_until_complete(self.game_loop()) 
     try: 
      self.loop.run_forever() 
     finally: 
      pass 
     loop.close() 

Game() 

这里就是我想要做的事:

  1. 玩家输入与游戏输出是异步,所以input()不会阻塞。这工作。
  2. 如果骨骼在3秒内没有中断,则准备进行攻击,攻击会对玩家造成伤害。
  3. 玩家可以输入任何文字来中断骨架攻击。

我该如何制作骷髅的攻击?我想要一个我可以随意中断的任务,稍后再调用回调。目前一切都被卡住了。 call_later从不呼叫。

+0

我不明白这是如何特别是asyncio的一个很好的用例。 – Goodies

回答

0

这是具有超时和回调函数的异步函数的模式。线索是捕获asyncio.TimeoutError并执行超时逻辑。在当前等待位置后,取消的功能将不会继续。

import asyncio 

async def slow_function(seconds): 
    print('starting slow computations') 
    await asyncio.sleep(seconds) 
    print('slow computations done') 

async def timeout_callback(): 
    print('timeout called') 

async def timeout_with_cb(fut, timeout, timeout_fut): 
    try: 
     await asyncio.wait_for(fut, timeout) 
    except asyncio.TimeoutError: 
     await timeout_fut 

loop = asyncio.get_event_loop() 
loop.run_until_complete(asyncio.ensure_future(
         timeout_with_cb(slow_function(2), 1, 
         timeout_callback()))) 

这将打印:

starting slow computations 
timeout called 

我想这可以帮助你适应你的例子(提供的示例不编译)。