我试图为文字游戏编写实时战斗系统。我希望玩家能够采取行动并且必须等待一定时间才能再次行动,而NPC也在这样做。
我写了一个小例子:
import threading
import time
def playerattack():
print("You attack!")
time.sleep(2)
def npcattack():
while hostile == True:
print("The enemy attacks!")
time.sleep(3)
p = threading.Thread(target=playerattack)
n = threading.Thread(target=npcattack)
hostile = False
while True:
if hostile == True:
n.start()
com = input("enter 'attack' to attack:")
if 'attack' in com:
hostile = True
p.start()
该示例适用于第一次攻击: 我进入攻击',敌对标志设置为True,npc攻击线程启动,但我得到一个' RuntimeError:线程只能启动一次'当我再次尝试攻击时。
有没有办法重用该线程而不会抛出错误?或者我是不是错了?
答案 0 :(得分:0)
问题是该线程已经在运行,并且由于while循环再次调用n.start()
,您无法再次启动正在运行的线程。
即使线程已经死亡,您仍需要重新初始化线程实例并重新开始。您无法启动旧实例。
在while True
循环的情况下,它试图多次启动一个线程。你做的是检查线程是否正在运行,如果没有运行则启动线程实例。
import threading
import time
def playerattack():
print("You attack!")
time.sleep(2)
def npcattack():
while hostile:
print("The enemy attacks!")
time.sleep(3)
p = threading.Thread(target=playerattack)
n = threading.Thread(target=npcattack)
hostile = False
while True:
if hostile and not n.is_alive():
try:
n.start()
except RuntimeError: #occurs if thread is dead
n = threading.Thread(target=npcattack) #create new instance if thread is dead
n.start() #start thread
com = input("enter 'attack' to attack:")
if 'attack' in com:
hostile = True
if not p.is_alive():
try:
p.start()
except RuntimeError: #occurs if thread is dead
p = threading.Thread(target=playerattack) #create new instance if thread is dead
p.start()
答案 1 :(得分:0)
我们从start()
方法开始线程。
之后,我们使用run()
方法,即p.run()
和n.run()
而不是p.start()
和n.start()
来重用同一线程。
答案 2 :(得分:0)
如果您只是想更改线程“链接”到的函数的参数,我通过创建子类并实现了reset方法,发现了一种重用threading.Thread对象的(巧妙的)方法。 / p>
class ReusableThread(threading.Thread):
def __init__(self, *args, **kwargs):
threading.Thread.__init__(self,*args, **kwargs)
self._default_args = self._target, self._args, self._kwargs
def run(self, *args, **kwargs):
super().run()
self.reset()
def reset(self, *args, **kwargs):
self._target = self._default_args[0]
self._args = args or self._default_args[1]
self._kwargs = kwargs or self._default_args[2]
在python shell中:
>>> r = ReusableThread(target=print, args=("banana",))
>>> r.start()
banana
>>> r.reset(("banana", "apple"), "kiwi", sep='\n', end="<<<\n")
>>> r.run()
('banana', 'apple')
kiwi<<<
>>>