2017-06-11 14 views
1

私は敵をノックアウトしなければならない学校用のボクシングプログラムを作っていますが、敵も数秒ごとに攻撃します。彼は攻撃しようとしているときに感嘆符を表示し、速やかに反応してブロックする必要があります。反応タイマエラー

基本的には、ボタンを十分に速く押さないとコマンドを実行するランダムな時間を生成することです(私の場合は攻撃)。反応タイマ。

私は、ブロック機能と敵の攻撃機能を同時に実行できるようにマルチスレッドを使用しました。将来、私はあなたが攻撃できるようにスレッドを追加したいと思います。

これは私の反応タイマーです:

from random import * 
from turtle import * 
from time import * 
from threading import * 

def Reaction(): 
    vTime = 0 
    while vTime < 3: #The time in which you have to react 
     vNow = time() 
     vStep = vNow + 0.25 
     while time() < vStep: 
      vJack = True #Useless arguments to fill up the time between each step 
      vJack = False 
     vTime += 0.25 
     print(vTime) 
     if vReaction == True: #Checking if you have pressed the key 
      print("Oke") 
      break 
    print("af") 

def key(): 
    global vReaction 
    vReaction = True 

def Block(): 
    global vTimer 
    while vTimer < 5: 
     onkey(key, "space") 
     listen() 

def AttackEnemy(): 
    global vTimer 
    while vTimer < 5: 
     vHitTime = randrange(4, 12)/4 * 1000 # Generating the random time after which the enemy is going to hit 
     ontimer(Reactie, vHitTime) 
     vTimer += 1 


vTimer = 0 
vBlock = Thread(target = Block, args =()) 
vAttack = Thread(target = AttackEnemy, args =()) 

vBlock.start() 
vAttack.start() 

vBlock.join() 
vAttack.join() 

print("End") 

私はこれらのエラーを取得するプログラムを実行している:

Exception in thread Thread-2: 
Traceback (most recent call last): 
    File "D:\Programma's\Python\lib\threading.py", line 916, in _bootstrap_inner 
    self.run() 
    File "D:\Programma's\Python\lib\threading.py", line 864, in run 
    self._target(*self._args, **self._kwargs) 
    File "G:\test getal.py", line 35, in AanvalVijand 
    ontimer(Reactie, vSlagtijd) 
    File "<string>", line 6, in ontimer 
    File "D:\Programma's\Python\lib\turtle.py", line 3662, in Screen 
    Turtle._screen = _Screen() 
    File "D:\Programma's\Python\lib\turtle.py", line 3690, in __init__ 
    TurtleScreen.__init__(self, _Screen._canvas) 
    File "D:\Programma's\Python\lib\turtle.py", line 985, in __init__ 
    "blank" : Shape("image", self._blankimage()) 
    File "D:\Programma's\Python\lib\turtle.py", line 470, in _blankimage 
    img = TK.PhotoImage(width=1, height=1) 
    File "D:\Programma's\Python\lib\tkinter\__init__.py", line 3539, in __init__ 
    Image.__init__(self, 'photo', name, cnf, master, **kw) 
    File "D:\Programma's\Python\lib\tkinter\__init__.py", line 3495, in __init__ 
    self.tk.call(('image', 'create', imgtype, name,) + options) 
RuntimeError: main thread is not in main loop 

私は数週間のためにこれだけ単にコードのすべてに新たなんですだから、私が間違ってやっていることとそれを修正する方法を本当に知りたいです。

PS:プロジェクトでは拡張ライブラリを使用できません。

答えて

0

タートル自身のontimer()イベントを使用するだけで逃げることができる場合は、タートルとのスレッドを混ぜて使用しないでください。ここでは、アクションを制御するだけでontimer()を使用してコードの私のリワークです:

from random import randrange 
from turtle import Turtle, Screen 

vStep = 0.25 # in seconds 
FONT = ('Arial', 18, 'normal') 
ROUNDS = 3 
TIME_PER_ROUND = 5 # in seconds 
TIME_BETWEEN_ROUNDS = 2 # in seconds 

def StartAttack(): 
    global vTimer, vReaction 

    magicMarker.undo() 
    magicMarker.write("!", align='center', font=FONT) 

    vTimer = 3 # you now have 3 seconds to react 
    vReaction = False 
    Reaction() 

def Reaction(): 
    global vTimer 

    if vTimer > 0: # The time in which you have to react 

     if vReaction: # Check if you have pressed the key 
      magicMarker.undo() 
      magicMarker.write("Reacted in time!", align='center', font=FONT) 
     else: 
      vTimer -= vStep 
      screen.ontimer(Reaction, int(vStep * 1000)) # recheck in vStep seconds 
    else: 
     magicMarker.undo() 
     magicMarker.write("Didn't react in time!", align='center', font=FONT) 

def key(): 
    global vReaction 
    vReaction = True 

def Block(): 
    screen.onkey(key, 'space') 
    # disable above event handler in after round ends 
    screen.ontimer(lambda: screen.onkey(None, 'space'), int(TIME_PER_ROUND * 1000)) 

def AttackEnemy(): 
    global vTimer 

    vTimer = -1 
    # Generate random time after which the enemy is going to hit 
    vHitTime = randrange(4, 12)/4 * 1000 
    screen.ontimer(StartAttack, int(vHitTime)) 

def NextRound(): 
    global vRounds 

    if vRounds > 0: 

     magicMarker.undo() 
     magicMarker.write(" ", align='center', font=FONT) 

     Block() 

     AttackEnemy() 

     vRounds -= 1 

     screen.ontimer(NextRound, int((TIME_PER_ROUND + TIME_BETWEEN_ROUNDS) * 1000)) 
    else: 
     magicMarker.undo() 
     magicMarker.write("Match Over!", align='center', font=FONT) 

screen = Screen() 
screen.listen() 

magicMarker = Turtle(visible=False) 
magicMarker.write(" ", align='center', font=FONT) 

vTimer = -1 # just to make these exist 
vReaction = None 
vRounds = ROUNDS 

NextRound() 

screen.mainloop() 

クリックして、それがキーボードイベントを受け取ることができますので、それをアクティブにするためにポップアップするウィンドウの上に。

私はあなたがに走った問題は、スレッドとの相互作用のTkinter(亀の基盤)であると考えている - あなたはこのルートを移動する場合、あなたはTkinter and Threads

+0

をチェックアウトする可能性があるscreen.listen()関数はしていませんキーを押すまでプログラムを停止しますか? – Rek3beef21

+0

@ Rek3beef21、no。これは、ウィンドウがデフォルトで有効になっていないキーイベントを受信するだけです。ドキュメンテーションによると、 "TurtleScreenに焦点を当てる(キーイベントを収集するために)。"あなたは一度だけそれをプログラムで呼びます。 – cdlane

+0

あなたのアドバイスや訂正に感謝しています。どうもありがとう!! – Rek3beef21

関連する問題