[Tutor] Event loop logic question

Alan Gauld alan.gauld at yahoo.co.uk
Sat Jun 18 06:05:10 EDT 2022


On 18/06/2022 06:04, Phil wrote:
> Thank you for reading this.
> 
> What I'm trying to achieve here is have the word 'stop' printed once 
> whenever no keys are pressed and 'forward' printed once even when the up 
> arrow key is held down.

I understand the second part, but not the first.
How do you determine that no keys are pressed - how you detect the
absence of an event? Usually there is some kind of dummy "idle"
event that you could use to trigger it, but I don't know your toolkit.
However you seem to be using the key_up event which will trigger
between every key press whioch is not, I think, what you want?

> I don't think this question needs any knowledge of Pygame Zero to solve

On the contrary, knowing what events are available from the toolkit
seems to be crucial to how you solve this. I can do it in tkinter (I
think!) but have no idea about PygameZero, which i'd not heard of till now!


> following code is my most recent version which seems to work the first 
> time through the loop but fails after subsequent 'up' key presses. 

Can you be more specific? What does "fail" mean? What does it actually
do? Does it print anything? Print too much(of what?) or crash? Is there
an error message?

> Debugging the event loop is difficult.

The usual way is to insert print satements into the event handlers or to
catch the event handlers in a debugger using breakpoints.

> direction = 'stop'
> stop_flag = True
> forward_flag = True
> 
> def on_key_down(key):
>      global direction
> 
>      if key == keys.UP:
>          print('up pressed')
>          direction = 'forward'
>          forward_flag = True
>          print('forward_flag ', forward_flag)

Its usual practice not to do UI changes(ie print) in the event
handlers but to do that in the draw/update/refresh method.
Just set the values in the handlers.

Another question - what should happen if another key other than
UP (or space) is pressed? Would you want to cancel the forward flag?

>      elif key == keys.SPACE:
>          direction = 'quit'

Why set direction to quit? It's not really a direction.
Why not just quit right here? If you did want a farewell
message then fair enough, although I'd tend to use a
flag rather than abuse direction...

> 
> def on_key_up(key):
>      global direction
> 
>      #print('stop')
>      direction = 'stop'
>      stop_flag = True

In other words should forward_flag be set to false here?

> def update():
>      global direction, stop_flag, forward_flag
> 
>      if direction == 'stop' and stop_flag:
>          print('stop')
>          stop_flag = False
> 
>      elif direction == 'forward' and forward_flag:
>          print('forward')
>          forward_flag = False
>          stop_flag = True
> 
>      elif direction == 'quit':
>          quit()

This feels wrong to me. I'd expect it to look more like:

def update()

    if direction == forward and not forward_flag
       print direction
       forward_flag = True  # only set flag after first print
    elif direction == stop and not stop_flag
       print direction
       stop_flag = true   # same again
    elif direction == quit     # do you really want this in update?
       quit


I hope these random musings are helpful...
My main suggestions are:

Take the print and setting of the flags out of the handlers
and put that in update. Only set direction in the handlers.
And also make sure you set all of the state flags to their
correct values when you change state.

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos




More information about the Tutor mailing list