简体   繁体   English

Python asyncio:可中断的任务

[英]Python asyncio: interruptable task

I am trying to make a barebones skeleton fighting game with 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()

Here's what I am trying to do: 这是我想做的事情:

  1. Player input and game output are async, so input() doesn't block. 玩家输入和游戏输出是异步的,因此input()不会阻塞。 This works. 这可行。
  2. The skeleton prepares an attack, if it's not interrupted in 3 seconds, the attack deals damage to the player. 骷髅会准备攻击,如果3秒钟内没有被打断,攻击会对玩家造成伤害。
  3. The player can input any text to interrupt the skeleton attack. 玩家可以输入任何文字来打断骷髅攻击。

How can I make the skeleton's attack? 我该如何攻击骷髅? I want a task I can interrupt at will and call a callback later. 我想要一个可以随意中断的任务,稍后再调用回调。 Currently everything just gets stuck. 目前,一切都陷入困境。 The call_later never calls. call_later从不调用。

This is the pattern for a async function with timeout and callback function. 这是带有超时和回调功能的异步功能的模式。 The clue is to catch the asyncio.TimeoutError and do your timeout logic. 提示是捕获asyncio.TimeoutError并执行超时逻辑。 The function that is cancelled will not continue after it's current await position. 被取消的功能在其当前的等待位置后将不会继续。

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

This will print: 这将打印:

starting slow computations
timeout called

I guess this can help you to adapt your example (the provided example does not compile). 我想这可以帮助您调整示例(提供的示例无法编译)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM