Tooling Tuesday - Inputs

Getting input with Python can be handled in many different ways, from the keyboard, mouse to complex sensors, all is possible. If you know how to get it.

But getting joypad / joystick / dancemat input is not very easy, there are ways using PyGame (which is excellent and works really well) but if you need something a little simpler, then perhaps Inputs is you things.

So what is it?

Inputs from Zeth is a Python module / library that listens for user input across a number of devices. It works with

  • Gamepads
  • Joysticks
  • Keyboard
  • Mouse
  • Sense HAT (joystick)
  • USB dance mats (yes I have one, yes I tested it, no there is no video)

and offers an easy way to detect a button press and react to it.

So how can I install it?

Installation

To install inputs, all you need is pip3 and in the terminal / command prompt type.

$ sudo pip3 install inputs

Keyboard Input

For Windows and Mac users, you can skip this bit, unless you would like to learn about user groups under Linux...

Reading keyboard input on Linux is only for root / sudo users, or users who are in the group input so by default we cannot read the keyboard input. So you can either run your code as root / sudo. Or add your user to the inputs group. To do that open a terminal and type.

$ sudo usermod -a -G input <USERNAME>

So I know what you are thinking "I can use this to write a key logger app!" and yes you can do that, but don't because you will get in trouble!

So how can I use it?

Detecting Keyboard Input

With the inputs library installed, open up your favourite Python editor...that's Mu right? ;) And let's start writing some test code which will detect when a key is pressed on the keyboard.

We start by importing the get_key class from inputs.

from inputs import get_key

Then in a loop we constantly update the object events with the key being pressed. The events object is a list used to store multiple pieces of information, more on that in a moment.

while True:
    events = get_key()

Now inside the loop we create a for loop that will iterate over the items in the list events and print out the event type (keypress), the event code (which key) and the state (1 == pressed, 0 == released)

    for event in events:
        print(event.ev_type, event.code, event.state)

Next we have a little fun, and use a conditional test to check in the L key has been pressed (1) and if so it will print that I pressed the key. When the L key is released, the elif condition is True and that triggers another print function to print that I released the key.

        if event.code == "KEY_L" and event.state == 1:
            print("Les pressed the L key")
        elif event.code == "KEY_L" and event.state == 0:
            print("Les released the L key")

If we put this all together, save and run the code we see something like this.

Detecting Gamepad Input

But what is special about inputs is that we can detect any USB gamepad input using a very similar sequence of code.

In this test I have plugged in my trusty "Super Nintendo" style joypad ready for use.

This time from the inputs library we import the get_gamepad class.

from inputs import get_gamepad

Then we create a loop.

while True:

Create an object called events used to capture the list of information that each button press creates.

    events = get_gamepad()

Lastly using the same for loop as before we print the contents of the list. In this case I simplified it to just print the button being pressed, and the state of the button, with 1 == pressed and 0 == released.

    for event in events:
        print(event.code, event.state)

Put it all together and save. Then run the code and you will see this.

Why not just use PyGame?

First let me be clear, PyGame is awesome and I encourage you to take a look at it. But to use gamepads with PyGame we need to create a screen / display that is generally used to display your game, and so the screen / display must be selected (in focus) so that any input is captured and relates to the game. This is cool, but if you want to run the code without a physical screen (headless) then it will get complicated quickly.With inputs we have a simple way to read keyboard, gamepad and mouse input without the need for using a screen / display, and this means that our robot / laser guided NERF turret will work without the need for a screen.

Keyboard Input With PyGame

Keyboard and gamepad input with PyGame is simple, and if you are making games with Python then this is the library to use.



For fun (I should get out more) I wrote a simple Turtle drawing controller using PyGame.

Here is the code which I am happy for you to use.

Disclaimer: This code was written under the influence of two cans of rather nice IPA, on a train ride home from Manchester. No liability for poor coding...so don't go giving me evils.

import pygame, sys
from turtle import *
pygame.init()
pygame.display.set_caption('Keyboard Example')
size = [640, 480]
screen = pygame.display.set_mode(size)
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                forward(10)
            if event.key == pygame.K_DOWN:
                backward(10)
            if event.key == pygame.K_LEFT:
                left(15)
            if event.key == pygame.K_RIGHT:
                right(15)

Conclusion

Inputs is a fun and rather handy library. The ability to just detect input from a variety of USB devices without the need for the full PyGame library means that we can write code that does not require a screen in order to be useful.

Happy Hacking!