【问题标题】:Python - How to trigger action in method from a different methodPython - 如何从不同的方法触发方法中的动作
【发布时间】:2019-10-10 06:15:24
【问题描述】:

我想以 1-5 秒的随机间隔在游戏中生成一个敌人。为了防止程序的游戏部分(移动角色等)在出现sleep 时暂停,我将整个代码拆分为 2 个方法,以便我可以有 2 个线程 - 一个设置 enemyspawn True 每 1 个 - 5秒,另一个控制角色。

遗憾的是,第二种方法不会在第一种方法中更改enemyspawn,或者线程输出错误。我已经阅读并尝试在 if 语句之前从 EnemySpawn() 检索值,但这不起作用(或者我做错了)。我还尝试将enemyspawn 转换为全局变量。没有改变任何东西。

def Gameplay():
    width=80
    height=80
    y = 720/2+height/2
    x = 720/2+width/2
    speed=2

    enemyspawn = False
    while True:
        #controll character here
        if enemyspawn:
            enemyspawn=False
            print(enemyspawn) #Spawn enemy here later

        window.blit(bg, [0,0])
        pygame.draw.rect(window,(100,100,100),(x,y,width,height))
        pygame.display.update()


def EnemySpawn():
    enemyspawn = EnemySpawn() #idrk about this line

    while True:
        sleep(randint(1,5))
        enemyspawn=True
        print(enemyspawn)
    return enemyspawn

Gameplay = threading.Thread(target=Gameplay)
Gameplay.start()
EnemySpawn = threading.Thread(target=EnemySpawn)
EnemySpawn.start()

线程错误信息:

line 51, in EnemySpawn
    enemyspawn = Gameplay(enemyspawn)
UnboundLocalError: local variable 'enemyspawn' referenced before assignment

另一个错误信息:

line 51, in EnemySpawn
    enemyspawn = EnemySpawn()
TypeError: 'Thread' object is not callable

【问题讨论】:

  • 我会使用 pygame 事件系统来做到这一点。看看我的this answer

标签: python multithreading methods pygame switch-statement


【解决方案1】:

在这种情况下,您不希望从同一个函数(递归函数)中调用函数。更好的方法可能是:

def spawn_enemy():
    # code that makes an enemy
    print("an enemy has been spawned")
    return True # would be "return enemy" after you create your enemy entity

def EnemySpawnThread():
    enemy_list = [] # to maintain records of all enemies made
    while True: # make enemies forever
        sleep(randint(1,5))
        enemy_list.append(spawn_enemy()) # call our function we made above which spawns enemies

目前这只会创建一个类似[True, True, True, ...] 的列表,但最终你可能会定义一个敌人类,它会变成[enemy_object, enemy_object, ...],这是更可取的,因为我发现删除对象的最佳方法是将它们存储在列表,然后del enemy_list[index] 删除它们(例如当敌人死亡时,它不会继续使用内存)。此外,它使您能够像这样进行迭代:

for enemy in enemy_list:
    enemy.move()
    enemy.attack()
    enemy.die()

这就是为什么您希望 enemy 成为具有如上所示方法的类。

附带说明,您可能希望将enemy_list 作为全局变量(或在您的主函数中),以便您的所有线程都可以访问它。否则,您将需要使用 python 实现内置标准的queue.Queue()

【讨论】:

  • 感谢您的快速回复!这非常适合生成敌人。唯一的问题是当我使用背景时敌人会很快消失。你也知道有什么解决办法吗?
  • @Varvalian 不,这听起来像是涉及未发布的代码的其他部分。我建议您将其诊断到代码的特定部分和create a MCVE。将其发布在此处将脱离“如何从不同的方法触发方法中的操作”的主题。一旦你发表了你的帖子,你就可以在这里发表评论,并在此处发表评论“@”我(就像我对这条评论所做的那样),这样我就可以获得查看它的通知。
  • @Varvalian 如果这篇文章实际上已经回答了您最初的问题,那么通常的做法是单击我的帖子旁边的复选标记以接受它作为答案(如果有更好的答案,您可以稍后更改也来了)。当您获得 15 名声望时,您也可以对有用的问题/答案进行投票。欢迎使用 StackOverflow!
  • 遗憾的是,我现在无法发布另一个问题(延迟 90 分钟)。我正在考虑在适合该主题的问题下用我的代码发表评论,然后在此处评论指向它的链接... @Reedinationer
  • @Varvalian 最好自己提出问题。您无法正确格式化注释块中的代码,因为它看起来像这样if my_test = True:print("yes"); for item in my_list:; process_item(item) 并且所有缩进和执行流程的感觉都被抛弃了(就像我的代码中的 for 循环嵌套在 if 中?......没人知道!!)我相信你可以处理一个小的延迟!另外,问题让您有机会获得和建立您的声誉(有消除延迟等好处),而 cmets 没有这样的功能
猜你喜欢
  • 2012-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-15
  • 1970-01-01
  • 2015-08-14
  • 2021-05-29
  • 2013-08-04
相关资源
最近更新 更多