How to ignore user input during sleep in Python 3?

2019-07-24 16:47发布

问题:

I'm new to programming and am stuck with this problem in a small RPG game I'm making. It's mostly text based but uses tkinter for a simple GUI.

During battles, I have a for loop that goes through all creatures that are participating in the battle, and executes their action one by one with small sleeps between each action. My problem is that when the user presses keys or clicks buttons, the commands are buffered and executed after the for loop completes. Is there an easy way to ignore the user commands while this loop is going? I've tried unbinding keys and disabling buttons, then re-enabling them when the loop is complete, but it still doesn't work. I've also read about flushing the user input but I can't figure it out. Since I'm a rookie, I think I'm missing some basic concept here.

Here's my code:

def battle_round(self, command):
    ''' (Battle, command) -> NoneType
    A round of battle where every creature gets an action.
    '''
    # Pause player input with mode variable.

    self.player.mode = 'wait'

    # Keep track of number of rounds.
    self.round_number += 1

    # Get initiative order for all mobs, party members, and player.
    ordered_creatures = self.initiative()

    # Get commands from each mob.
    for mob in self.mobs:
        mob.command = self.determine_mob_command()

    # Check battle speed option.
    delay = 1

    # Begin actions for all creatures.
    for creature in ordered_creatures:
        # Delay between actions. Write a space between lines.
        self.text_window.update_idletasks()
        self.write(self.text_window, '\n')
        time.sleep(delay)
        # Player action.
        if type(creature) == Player:
            if command == 'standard_attack':
                self.standard_player_attack()
            if command == 'retreat':
                self.retreat()

        if type(creature) == PartyMember:
            pass

        # MOB action.  
        if type(creature) == MOB:
            if creature.command == 'standard_attack':
                self.standard_mob_attack(creature)

    self.start_next_round()

I'm using Python 3.2.3 with Tk 8.5 and IDLE 3.2.3. My OS is Windows 7.

Thanks in advance!

Edit: Thanks for the replies so far guys. I may be in over my head here since I didn't even know what threading was until just now, and I'm not sure how I would go about reading and ignoring user input. As far as the code for the user input goes, I have a lot of it. I'll copy and paste some here:

def attack():
    if player.in_battle == True:
        if player.mode != 'wait':
            player.current_battle.battle_round('standard_attack')

def retreat():
    if player.in_battle == True:
        if player.mode != 'wait':
            player.current_battle.battle_round('retreat')

# Set up battle buttons.
attack_button = Button(battle_button_frame, text='(A)ttack', command=attack,
                     width=10,)
attack_button.grid(column=1, columnspan=1, row=2, padx=5, pady=5)

retreat_button = Button(battle_button_frame, text='(R)etreat', command=retreat,
                     width=10,)
retreat_button.grid(column=2, columnspan=1, row=2, padx=5, pady=5)


battle_button_list = [attack_button, retreat_button]

These buttons, for example are to have the user either attack the selected monster, or attempt to run away from the battle.

I also have several key bindings:

# Bind Keys
root.bind('<Escape>', func=keyboard_cancel)

root.bind('<Control-Key-m>', func=keyboard_move_mode)
root.bind('<Control-Key-M>', func=keyboard_move_mode)
root.bind('<Control-Key-l>', func=keyboard_look_mode)
root.bind('<Control-Key-L>', func=keyboard_look_mode)
root.bind('<Control-Key-t>', func=keyboard_talk_mode)
root.bind('<Control-Key-T>', func=keyboard_talk_mode)

root.bind('<space>', func=keyboard_begin_battle)

root.bind('<Left>', func=arrow_key_select_left)
root.bind('<Right>', func=arrow_key_select_right)

My problem remains that when the for loop with the sleeps is going, if the user presses a button or uses a key binding, it will get executed as soon as the battle round is over. (About 7 seconds if there are 6 monsters and the player.) I am a complete beginner at this so I apologize for not being clear with my post and for my code being a horrible mess.