When reading states is not enough¶
At the beginning of the section about interaction we mentioned that there are two basic ways for a program to get information about user actions. The first way is to read the state of the mouse and the keyboard, and we are familiar with that way by now.
Reading the states of mouse and keyboard is easy and sufficient for many applications. However, in some situations it is not the most convenient way of doing things. For example, if we wanted to know when the user clicks the mouse:
frequently reading the state of the mouse may result in multiple consecutive readings indicating that a mouse button is down, but we do not know if it is all the same click or there were more clicks.
infrequently reading the state of the mouse may result in that the user presses and releases a button after one reading and before the next one. In this case, the program will not receive information about that click.
Let us look at the following example.
Example - broken switch:
The following program draws an image of a wiring diagram for each frame, and then over it images of a switch and a bulb. The idea is to “turn the light on and off” by clicking on the switch.
When solving the task by reading the state of the mouse, various unwanted behaviors may come about due to the shortcomings described above, such as not reacting to a click (reading the state too infrequently) or flickering of the light (reading the state too frequently). Even if your speed of clicking is just right, so you can avoid these unwanted effects and normally turn the light on or off, someone who clicks faster or slower could feel the problem.
Try the program out with clicking at different speeds.
Information about state changes¶
As we mentioned in the introduction to this chapter, we can also track user actions in another way, which is to use system events. The events we deal with here can be understood as changes in the state of the mouse or keyboard (though there are other events, such as those generated by the system clock). For example, when a key on the keyboard or a mouse button goes down, the computer’s operating system receives a signal from the input device and registers it as an event. The same happens at the moment of releasing the keys (buttons), changing the position of the mouse, etc.
All events are logged and remembered, so it cannot happen that we miss a user’s action, like when we only read the status.
The PyGame library allows us to get one object for each event with information about that event, to examine what sort of event it is, and to programmatically respond to the event as needed.
Using events in programs¶
In programs that use events, we will write a special function
handle_event(event) (you can give it a different name). This function gets a PyGame object event as an argument, which contains all the necessary event information. We add the name of our event processing function as the third argument in the petljapg.frame_loop function call. This enables our handle_event function to be called for each event that occurs while the program is running.
Now let’s look at how exactly we handle the event.
In the handle_event function, we check if this event is of the type “a mouse button going down”. We do this by comparing the event type, stored in the
event.type field, with the PyGame constant
pg.MOUSEBUTTONDOWN, which has the described meaning.
If the event is of the type we are interested in (moving a mouse button down, that is, start of a click), using the command
mouse_point = event.pos we place the coordinates of the point where the mouse was at the time the event occurred in the variable mouse_point, because we want to know what the user clicked on.
The following commands check if the user clicked on the switch, and if so, change the value of the logical variable switch_on, which shows the state of the switch.
Example - switch:
This program does the same thing as the previous one, but uses the mouse down event so there are no unwanted effects.